diff options
204 files changed, 65134 insertions, 9 deletions
diff --git a/share/Makefile b/share/Makefile index 6363f07..330a31c 100644 --- a/share/Makefile +++ b/share/Makefile @@ -1,6 +1,6 @@ # @(#)Makefile 8.1 (Berkeley) 6/5/93 -SUBDIR= dict doc examples info man me misc mk skel \ +SUBDIR= dict doc examples info isdn man me misc mk skel \ syscons tabset termcap timedef zoneinfo .include <bsd.subdir.mk> diff --git a/share/isdn/0.g711a.uu b/share/isdn/0.g711a.uu new file mode 100644 index 0000000..69fb7c6 --- /dev/null +++ b/share/isdn/0.g711a.uu @@ -0,0 +1,322 @@ +begin 644 0.g711a +MJJNKJ^OK:^LKJVO+*ROKJZJJJJHJ*BJJJZNKJBKJZFIJZBJJJRLK*^OKZVMK +MB^NKJBKJ*JJJJJJKJZNKJZNJJROKZ^OKZROKZRLKJZJJJJNJJJHJJBHJJBIJ +MRDKJ*JKKZVL+"PN+BPN+:RNJ*NKJZNJJJJJJJROKZ^OKJZJJZNIJ:NKJ:NJK +MZVN+:^MK:^LKJZHJ:FKJZJHKZ^LKZ^LK*ZJJ*BJJJZNKJRHKBZNKZZJJ*RNK +MJZLKJZJJJROK*^LK*ZKJ:FIJ:NKJ*JNK*RLKJZLKZ^OKZRLKJZHJJBLK*ZNK +M*ZNKJZNKJZLKJZHJZBKJJJJK*ROK:VL+"ZMJJFJ*ZBKJJBLK*RLKZVOKZ^LK +M*RNKJJKJ:HJ*:FIJ*JJKZVN+:^OK*RNK*ZLKJJJKJBHJ*BJJJZNKJZJK*RLK +MJZNKJRLKJZJJJZHJ*BIJ*^NJJZNJJZNK*ZNK*RNK*ROKZ^MK:^OKZRLKJZLJ +MZFJ*BFIJ:NKJZBHJJJJK*^OK*RLK*ROK:VMKZ^LK*RNK*^OK*ZNJJBKJ:FIJ +MZFIJ:BIJBBNK*XL+"VMK:^OKJZJK*^MKZVMKZZLJ*FIJZBHJJJJKJBHJJJNK +MJZJJJZNK*RLKJZNJJRNKJZNK*^LKJZNJJJJKJJJKJJJKJJJJJRNKJVL+*^OK +MJJHJZBKJZFKJZNJJJJLK:XMK*ZNKJJNK*VN+BVN+:^LK*ZNKJBKJBHJ*:BJJ +MJROKZROK*ZNJJJHJ*JJK*ROKZVOKZRLKJJJJJJKJRLKJZNHJJJMKBXL+"XN+ +MZZNJ*BJJJJJKJZNKJJJJJJHJ*BHJJBLKZRLKJZJJ*BHJ*BJJ*ROK:VOK*ZNJ +M*JHKZXL+R\L+:^NK*BKJB@H*"FKK:ZLKZRMK:^LKJRKJ*BHJJJJK*ZNJJBJJ +M*NHJZNKJ*BHJ*JHK*ROK:XN+"PL+BXN+:^LKJNIJBFKJ*BHJJBKJ*JJKJZNK +MJRMK:^OK:VMKZXH**NKJJBHJJZNKJZJJJZNJ*BHJ*JLK*RLKZXN+BXN+BXMK +M*ZNJZHH*"@J*:NHJJRLK*RLK*^OKZRNK*ROKZ^LKJZNKZVN+:^LKJNIJBHIJ +MJROJJJJJJZJJJZLKJZHJZFKJZBJJJROK:VOKZVMKZRNKJJJJZNJJJZNJJRNK +MJRNKJZJKJBJK*^OK*ZNK*ZLKJZNJJZNKJRNK*ROKZVOKZZMJZBNJJNLKJRNK +MJZNKJZJJJZJKJBKJ*JHJZBHJZNHJJJNK*ROKBPL+BVOK*ZHJ*BHJZBJJJROK +MZROKZRNJ*NKJZFIJZBJKJROK:XN+BPOKZTL+JRLKJZNKJZHJZFJ*BHIJZNHJ +MJNIJZBHJJJNKJVN+BVN+BPO+2\N+ZZLJZFIJZNIJ:BHJZBHJ*NHJJBOKZ^N+ +MBXN+:^LK*RLK*ZNJ*NIJNLIJ"FHJJNO+RPL+R\N+ZRNKJJJJJJJJ*BJJJZLJ +MZNKJZFKJZNHJ*JJK*^MK:VMKZZNJ*BJK*^MK:VLK*ZNK*NKJ*BJJ*JJJJRJJ +MJBHJ*JL+"^L+B^LKZ^NKJBKJ*JJJ*JJKJJLK*ROKZ^NKJZJJJBKJZNJJJJLK +M*^MKZ^LKJRKJZBHJJJJJJJLK*ZNK*RLK*ZNJJJJJJJNK*^LKZ^MKZ^JJZZJJ +MJBJJJJHJ*JJJJJNJJRNKJZNKJZJJ*JNKJ^OKZVOKZRNKJRHJZNHJJBKJZBHJ +MJBLKZ^LK*ZLKJZJJJJJKJJNKJROKZRNK*BHJ*BKJZZMJ*BHJ*RNKJZNKJRNK +MJZOK:VOKJZLKZRLKJZLKZ^OKJZNKJBKJ:FIJZNHJJ^OK:VMK:RLK*RNKJJNK +M*RLK*RNKJNHJZFJ*BFKJ*JNKJNJ*JFLKZ^OK*^OKZ^OKZ^OKZ^LKJZHJJBHJ +M*BHJ*FIJZBJKJZNJJJOKZVMK:XMKZ^LK*^OK*ZNJJNIJBHIJ*JHJ*BHJJJHJ +MJJLKBPM+2\N+BTMK*JIJBHH*"FIJZNJJJJJKZ^OKZRNKJZOKZVMK:VMK:VOK +MJRIJB@H*BHIJZBJJJZNJJJHK:VN+"PN+BXMKZVOK*ZNJJJNJ*NIJZBHJJBIJ +MRFJJ:BJJ*JJK*^MKBXL+BXMKZZNKJJJJJJJKZ^LKJZLJ:NKJZBHJ*BHJ*BJJ +MJRMK:RLK*RLK*ROK*RLKZRNKJZJJJBHJ*BHJZBKJZBJJ*BO+:ZLK*RN+:^OK +M*RLK*RLK*RNK*RLKJ^IJ:FIJZBJJJZNJJZLK*RLK*RLK*ZNJJJJJJZNJJJNK +MJZOKZVMKZRNJ*BJJJRLKJZJK*^MK:VO+BZHK*RJJJBKJ:NHJ*FIJ*BHK*ROK +M*ZNJJBKJ:FKJ*JOKB\M+RVLKJZOJZNJJ*^OKJZNJJZNKJJHJ*BKJ:JHK*^MK +M:VOKZRLKZZOJ:FIJZBJKBRNJ*ZJJJJJJJZNK*RLKZ^MK:^LK*ZNKJJJKJRNK +M*ZNJ*NIJZNHJ*BJJJROKZXOK*ZNK*BJJJJHJ*BKJZNHJJJOKZ^LKJZNJJJOK +MZ^OK:ZOJ*^NK*ZNKJZOKZ^OK*^OKZRNKJJLJ*JJJ*FIJZBHJ*JHK*VOK:VOK +M*RLK*RLK:VOKJRIJ:HJ*BFKJ*BJJJJNKJJJJJJHJ*BJJJRMKBPMK"[N+ZVOK +M*ZNJ*NHJ*BJJJNKJ*JJJ*BKJZBHJ*^N+RTM+"XOK*^LK*FJ*"FKJ*JHJJJJJ +MJZNK*ZLK*BKJZJJK*^OK:VN+BXMK:^NKJBKJ:NJ*2NJJZBHJ*JHKZVN+BPN+ +MZRLK*RNKJZHJ*JJKJJJKZRNKJRIJB@J*ZJJK*VMKZVOKZRLKJZJJ*JJKJZNK +M*RLKJZNJ*BJJ*JHJJBHJJJJJZJN+JJJJZBJKJRLKZVMKBXOKZROK*ZNK*NHJ +MZNJJJRJK*^NKJZNJJRMK*ZLK:RLJ*ZJ**RJ**NKJ*VLK*^KJ*NJJJZOKJZNK +MJ^OK:PO+R\L+JXHJZ@H*BFKJZ^JKJJIK*XNKJZNKZRLK*ZNJ:NJ*:NJJ*^MK +MZXN+:VNKJJJJJNJJ*@KJRXH+*BK+*GMJ"XJJJVHKBJIJZBKJJ^JJJRN+ZXN+ +MNRLK*ZKJ*NKJZBJJ*RLK*ROKZ^OKJRNK*^MKBVOKJZHJ:HJ*BFIJZBHKZRLK +M*RLK*ZJJZNHJJJOK:XL+"VOK*ZNJ*FIJZNKJ*JNK*RNK*^J**RLKBPN+BVMK +MZZNJZBHJ*NIJ:NKJZBJKJZHJJJJJJZNJJZLKZVN+BPL+B^LK*RNKJZNJJBKJ +M:FIJZBKJJJJK*^LKJJNKJRLKZVMKBVMK2SL+"VNJ:FH*"@H*BFKJJJNKJZNK +MJJJJ*JJJJZOKBXN+:XMKZ^NKJRHJZNKJ*BHJJBHJ*BJJJ^MKZRLKJZNKJRLK +MZVN+BVMKZ^OKJZKJ:FI*NHH*BBJJ*VN+BXL+B^OK*ZNJJJJK*ZNKJJJKJZNK +MJZKJ:NIJZNHJZNHJJBOKBPL+BXMK:VOKZZNJ*NIJZNKJZBJJJRLKJJNKJZOK +MZ^OK*XL+JJNK*JLK*RNJJBHJZFIJZBJJJBLKZ^OK:RNKJJLK*ZNKJZLK*^MK +MZ^LKJJHJZNHJJBJJJZNKJZNJZBHJ*JJKJRLKZVN+BXN+:VOKZ^LKBLKJBHKJ +M*JJKJJJJJJNK*RNKJZNKJJJJ*BJJJROKZROKZVMK"XMKZRNK*FIJB@H*"@IJ +M*BMKBVOKZRNJJJJKJ^MK:XMK:^LKJRHJZBHJZBHK:RHJ*FKJJJJJJROK:XMK +MZVN+B^LKJFIJZNKJZNJJJZNJJZNKJZJJJ^OK:VMK:^NJZNKJZBJJJRLKZRNK +MJZLKZRNKJZJK*RLKJZKJZNHJ*@H*JZJK:XL+"VMK:VLKJZNJJJNKJROK*ZNJ +MZNIJ:FIJZNIJZBHJJBMK"\L+RPMK:ZLJZBHJ*BJJJJLKJRNKJZNJJBHJ*JJK +M*ZLKJROKZZNK:VNJJZLJJBKJZNKJZBJKZXN+"PMKZRNKJZLK*RLKJZHJZNIJ +MZFIJ:FHJJJLKZVMK:VMK:^OK:VMKZ^LKZ^OKZZNJJBHJ*BKJ*BKJ*JHJ*BH* +M"JJJJ^LKZ^OKZ^OKZ^OKZ^LK*RLK*RLKJZNKJJNKJBJJ*FIJ*BHJ*BHJJJHK +M*VMK:VN+:^LKJZJJJZNJJJJJ*RLKJZHJZFJ*:NHJJ^OK:TO+ZXOK*RLKJZNJ +M*NIJBHJ*:FKJ*BJJJRLKZ^OKZ^LK*^N+BPL+"^LKJZNJJZHJ*NIJ:FIJZNHJ +M*JHK*^MKBVOKZ^OK*ZNJJBKJZJHK*VN+JZMKJRHJZFIJZJHKZ^OKZ^NKJBKJ +MZNKJ:BHJJBLK:VN+"XL+:^LKJRHJ*JJJJZJJ*FJ*ZBJKZ^OK:RNKJZNKJROK +MZ^OK:VOKZRLK*ZLJ:FHKJFJJ*BJJ*BHJ*BJJ*^OKZ^LKJZJJ*JJKJZNKJZNJ +MJJNKJZNJJJJKJZLK*ROK*^OKZVMKZRNJJJHJJJJJJJLKJROK*ZLJ:NKJ*JJK +M*ROK:RJK:RNKJZJKJZNKJJJKJZNKJBHJ*BJJ*^OKZRNJ*BKJ*JJJJJNJJROK +M*RNKJZOKZ^NK*ZNKJZKJZBJJJBLKJZJJ*JJKJZLK*RMK:XN+:VMKNPNJ*ZKJ +M:FIJBFKJ:BJJJJNKJZJJJJNJJZLKZ^LK*ZLKJJNKJROK*ZNJZFIJBHIJ*JHK +MZXN+BXN+ZRNKJZNKJZNJJJNKJRNKJZHJ*BHJJZOJJBLJ*JNJ*^OKZ^LKZRLK +M*RLKJZJJ*BKJZBJJJRLK*ZNJJJJKJJJJ*BHJJJLKJRJJ*BJJJJHK*^MKZRLK +MJZJKJRMKZ^LK*ZNJZNKJZNIJJHN+ZXMKZRLKJROK*ZNJ*BHJ*NJJJZNKJJJJ +MJJJJJJJJJJJJJRMKBXN+BVLKJZJJJJHJ*BHJ*BHJ*BHJ*JJJJJNKJZJJJJLK +M*ROKZXN+BVOKZBOKJZNKJJHJ*BKJZJHK*ROKZ^LKJZNKJZLJZFIJZBJK*^NK +MJZLK*RLK*RNKJZNK*^MKZZLKJZNKJZNKJZLJJJHJ*BJJJ^MKZROK*ZHJ:BIK +MJNJJZNJJJJJJJJNK*ROKZVMKZ^MKZXN+:VLKJZHJ*FJ*ZNHJJRLK*RLKJBJJ +M*^LK*RNKJZJKJZJKJZLKJZHJZHH*BFKJZBJJJZJK*ROKJRKKBVO+RTM+RPMK +MZRNJJNKJ:FKJ*BHJ*JHJZFJ*"LH*BNJJ*^MKBPL+"VOKJZHJ*JHK:XMKBXOK +MZRLKJZJKJBJKJBKJ:BHJ*JJJJRNKJNJKZZKJJBKJ*JJKZ^LKJRNK*RLKZ^LK +MJZLK*^MKBVN+:^MKZRNK*ZNK*NIJ:NKJ:@H*"@IJZJOK:XN+:^OK*^NKJJLK +M:VN+BXN+ZRNJ*NIJZ@KZ"NJ**JJK:XN+BVOK*^OKZ^OKZ^LKJZHJ*BJJ*BHJ +MZFJ*"@H*:BHJ*VL+BVOK:^MKZ^MKZ^OKZ^OK:XOK*RLJ:HH*BBHJJJHJJZNK +MJRKJ*XLKJBLKJRLJZNJ*:NIJJJJK*^MKZVLK*VLK*ZNJJJOKZVMKZVOK*ZNK +MJRLKJJKJ:FH*"HH*:FIJ:BHKJVOK*ZNKJZLKJJNKJVMKBPL+:XLK*BNKJBLK +MJRLKJRNKJZNK*RNK*RNK*RNKJZNK*NIJZNIJ:FHJZBJJJBKJ*JJKJZJJ*JHK +MZ^MK"PN+RXOK:XN+BPN+BXMKZRNKJBHJ*FIJ:JKK*NJJZBHJZBHJZBIJ:BHJ +MJZNJ*BHJ*JLK*^N+:VMKZRNKJ^MKZVMKZPO+BXMK*VO+BVN+ZZNKJNIJ:FIJ +M:FIJ:FKJZNJ*RDI*RLKJ*JHKJJIKBVMKBXN+:XLK*\N+:XN+*^OKZXN+"PN+ +M:^N+ZZJJJJKJJBLKJ^MK:RNKJ^J*RKJZ.KI*NCIZ^CI*"FJKJZLKJZIK:^M+ +MN[L[^_O[.SN;>SL+"^OK*RHK:^LKJZHJ*BJJ*BHJ*BKJZNKJZHJ*"DI*NCKZ +M^GKZ^CI*R@IJZJHJJXL[^QM;HZ-;VYO;&WN;^TM+"XMK*^LKJNKJB@J*BKIZ +M:BKJJBIJBHH*NDJZ.IH:VMH:&AJ:.@J*:JJ+RSM[>Z,C8X/C8R,C(R.CF_M+ +MN[N+JNJ*"CKZ^OHZ2@IJ:FJJ*ZLKJNJ*RCIZ>II:(B):^DJ:^LK*ZNHJZVL+ +MNYM;8R-C8X-C@X-;VWL[^_M+BZNJBLK*2KKZFGI*"NJJ*XM+N\L+:ZJ*2AHB +MXN(BHEK:FAIZ^CK*"NJJZ\L[>UMC`X.C&R.CH^.C.SM+NTO+2VLKJ^J*.AH: +M&AH:.LIJJVL+2_O[.[N[BZL*^EHB8F*"`@+BHAHZRFHJJRL+N_M[HR.CXR.C +M8^.C&WM[FWO[.\OKZXMKBDIZVEKB(B+:"BHKB\N[.]L;F_N[:RI*>AK:6B+B +M(EI:&AJ:>CI*"BKK"TN[>YL;V^/;6UN;>_O[.YN;&YO[.[L+ZZJ*RCKZFIIZ +MFGHZ.DJJZXL[F]L;^_N["RJZ&B+B(B(B(AIZ^CI*2DH*:FJJ:XN+2SM[FQO; +M6Z-;FYM[>QO[NSO[.\M+"XLKZ@H*RIK:VMK:FCH**JOKRWO;VWO;&XLJ"AJB +M(H)"LH):&OHZ^FKJJ^MK"\L[>YNCHZ,CVWL[^[O+R\L+"PL+"VOKZRNK*RLJ +M*HH*RDIZ&GKZNDJ*ZVOK2QM;(R.;^[N+:OK:(@)"P@*B&AKZ.LHJJZHKZ\L[ +M._M[FYN;>_N[^_N[NWO[.TO+RPOK*^NJZHI*"LK*"LHZNDJ*BDH*JFLK2QO; +MHR,;^TOK"IHB@H+"0@*BVIHZBBIJJJOK:TN[^_O[F]N;._L+2TL[NWO[2[L[ +M.[L+:VLKJNIJZHI*FIKZ.OIZ^BJJ:HO[>QM;F_L[:[J:HF+BXN(B&AJ:NOI* +MZJJJZ[L[FQL[F^-;^]M[NXOKJRM+R\M+.YM[NXN+:^NJ*HH*"KKZ&AJ:2DKJ +MZZMK.WO;(UO[^[NKROJB8F("`B(:6AIZ>OKZ2@JJBPL;FR-C@^/;>[M[RPMK +M"SL[NTN[2POK"PN+JZIJBFK*&IIZ.KJZ"HOKJCN;VR.C.SO[JCJ:8L+",C)" +M6IK:&MI*BBJK"SO[^YNC`V-;&SL["XLK*@O+"RM+R[O[BZL+ZZNKJNJ*:DK* +M2KKZ"BJK"RO+HUMC8QN[.XOZ(N*R\E*N$H(B@IIZ"BL+JJL[R\N;FV.;(_L; +MXYM[J[MKRPM+>TL[>SL+NZLJ"ZJZ^CJZ^B(Z.KK*:[O+2]N#PT,C6UL[JOJ" +MDN[NC@ZNDO)"&KHJ"PM+HP,;H]LCFYO;BYM+Z\M[^UNC>UL;FTN#^Z.CJVL* +M"MIZ0J):8L):JHNJ:GOCTW-#@R-;REJRTFY.?CZN$JY"NNK+:WL;LR/;L^,S +M0]M+(YL[*LM[.TL[(Z-;8UO;NTOJJ@HJFIJ"6F+2$AHS`PH+[^_/SX.SCR," +M+@X>7F;&9K[^OI**ZUN;,\_/4_//C^\S8Z.SF_K*JKO*JZI+0PO[2P,;F]M+ +M(ZL*(OIB+DYJO^JR#X_3I^]*CS]BGHY>A@;VUL:>AA[Z6U.?IV<WQU^G)\\# +M2R(BVFX^0D*N6B+JTW/K\R_3<X.+*\OBDEJRCMHWYY)GMV\71UKOAW+&!M;H +MZ(BXZ$9VMBZ+KZ=G-VF)5ZGI%\??@VKZ7O9&1G8VQN:2JRN/AP?G9V>GIU-K +MRC(>1J;G]Y8[R4^WJ<M[Z0MH!L:(N,B8"(8H*,(/,Z<W5\FYJ5=)J5_/>V)N +MAN@V!JA6!OZR>ZIOUW?']]<'IX^Z"@*&%H<)*+(9$Z>)<EY7:ACH=OC82'@X +M#H86+Q<'=[G).9FI]^F'[HY.EO:HR%8F=D;K<P\'!T>IJ:<GQ^^KLGZB:<GV +M4Z'G/V<29N^V`)@((N&@B#LXI.8D)V=D9N4=G1^OV5O;HZ&AHIL*>#O]' +MYP>'M]<G&R,/:EXF!N:Z>>%F"9'W"<G^IJ/(T``@</"`6#B:#Z/9`>'AP8$9 +M&8?Z^_:86+B8>"@H$B?_'RFYJ=<7YU^;;E[.7A:V1N;7L3EN\3%7V9^H9F9` +M[$!`T##@..:I5^E!<<%A`2&)1UYHZ/B`8+B(5HZ;=[E)Z0DY5T]KKKZ&J"C& +MYN:F?J+Y+6'.D1&7^4(@2"B0S-#`$,!XUA]A81GQK;&AF:DC3GC`()A@(%9R +M_REIR2$AJ:<'P^:H:`C6YC:F@_\_:1&MZ?F1:0>G8+"@P.R,,`!@=@Y/X7%! +M@3'Q65=3UHBX`+`@""@&#^G9X5EYF0DOYI;H2#@8.$:NN\]?(<V-QV&MUQ?N +MK!"`D`Q,<*"8RI^7,>T188%!.:JV&.!8`#`@]NL/=QEA@>%)*5>+*'@8N$A( +MR';O-W_W<;U19T'!;T>X;-#`D&P,,"@.1XDY\>U18;FYU[98@$"`H"#XCBD9 +M>=F!8=GI+XY&B!C@V%:&9K+?-\FM/;'S03%?M@"LT!`0+`SPPC<W"6'1K1&! +M"5^OAN#PL&"@&.@;:5GAX2&A6>G+MBB(>*"8Z$;.8_^'`3T-%T=!86?@[*QP +M4!`L[&"W(1EI(2UM\3GO;H[68)"0X';F]FLY`0'9.?D)!X+H.,AHB`CH/L^G +M?[GM3<$O%QEY9JQLD'!P<-"PZ"G!P7G9$>TQYXAH9FB`D/"88D]/YXF!L>'I +MI]]_[DB@&.BV-C:N#U=!S8U9OW>A6<B,#)#`\"RLX+[I@;%AX3%1D6D(V.BH +MH)"06%+?AS<)(8'A&1>K#OX&B-AX%GX.\ONI,8WMX5_CB7DVK`SLL&#PT`#V +MJ6%!P0$!04&9LCA8^#C@0&`H[RF)21FA67EI/WZHZ%8HR$BHCJ.G6:UM\0FS +M1]DW(.R,4(#`D/!8VDGA`;&Q`6&A:>N(H""@H*`8J!M7R7G9&7D)U]_R%HB( +MJ*CHJ";#27'M$=E/<PG)9C!L[##@@$"`:"?9@<&QP6$9:0>B:"!@X)C(Z`:[ +M5WG9&3D)U^?##O9HR&C61B8RJ;'MK6'?VA?)*V#LC!"`8`"`R-.YX<$Q,0%Y +M]U\S9I@`P*#H!KXZ)\E9H9D)=S]*GL:H"$B(]G[+"?$M42$_BRE)*H!LC-"` +MX```N(\9@4$Q,0'Y1U-*1IC`0"#H'H*;A\FAH1G)-R\RYO:H"+A(*/ZW@:TM +M,<F3IXGWZ!`,;'#@(&`@%M=AL3$Q06')7ZO^Z""P0%AVPLOO%WGA(7DI)YN. +M1JB(N/A(UFJYD>VM@?>/*0FCX.S,+$`@X("8.GD!,?'Q0:'7HXXV.(`P`/B& +MZX^'B5GAH;F7#\(&J(@(2$AHQCNY<>TMP3=JA^EC(.Q,[$"@H.`X&]E!\?$Q +M0:$WP@:H^(`PP/A>4Z?WR:'AH;F7KX[VZ(@(R`CH1JM)<6WM07?B?U>;(.Q, +M;+!8&*`X.UFQ<7$Q02$76D;HF(`P0)CF+^?WR:'A(3EW<P[VZ`C(R(BHIHMG +M>9%M[<&')IH?SF!L3.Q`&'AX5D=A,?$QL<$9WV;HR-@`L`#(`B?W*3DAX5D) +MAPJ&Z,@(B(AH%H[/]SDQ[>TQ]S;FDZX@[$QL0/A(N'8W83$Q04$!&=^V"+C8 +M@$"`B#H'%^DY(>$9::>B!NC("(AH*+82?_>7R4$M[4&_"*@*ON#LS"Q@"&@H +M+FEAP0'!P6&),FC(R!A@`*#&#_>I"9FA64EWT_[6B`CH**AV?H/'%S<W&1'M +M<2DH..:BR'!L[$`X*/;"]YGA80'!X>FBUBAH^.#@F$:#A]<)^1F9R1<3IJCH +M**@H*+;R;V='1X=G";&M<6FH>(8#%D`L+$`XZ';:1PF9H8'!66>^Q@:6^"!8 +M:-Y;)U?)N3FYB4>*QA;V=BAH%HZSSX\?AX?/6ZFQ40%/"&AC/VBP4)"`^"A. +M+Q]'N6%!X1=J8D)FB-@8R%8^3Y<IZ8DY^:DC_B:&EFCHMOXRBP_GYX\S\WM/ +MV9'QR?XH8B<&8/!P0.`XYH__'XEAL6$I"^+RYJ@X&'B(_J>7=ZG)>3D7DV)> +M%NCHJ+;F$B]GA^=?'S];#JYI,3%)RF;";^;8`##P@`@NPRION6&!6>E/(J;& +M1NAX^%9*Y\?WZ0D):9?O3I96EE8H=K[CG^='ET=_H^).QJCRH7%AJ2\;7Z.H +M&,`0\*#6SKY:*:'A(1E7@S[>SC:X^.C^4^>WUQ=7::G_;C86UE8V?JXZOW<I +ME^>_@ZZ&-O96J#^QK0')9R_OO@B@D"P0H':NFB<YH6$!(5?R=C:&%FAHZ,:# +M%VDI]Q>I1W-.%NCHMCX.+MOG5^FI1X_RIF;&=A96MK?QK4%Y9XHZ9DA@4.R0 +MH$9+OZEY(8'!68>F**B6J&@(Z/YGB<GI=[>'OVLFZ`CH!BYJ[V?WJ2E7AUL^ +M-BCHUK;&!AXI$>WQH4>^9JAX`*SLD"`&WRDYV:$!0=D?-DBX"*C6Z*AR][DY +M:?<?KY-*AN@(*(;BS\<W%RDI]Y^J'M9HZ*AV9JY:JNF1[?&9WT;H2)A@T"SP +MF`[W21G9&2'A22^6^-BX]HY^?J/W";F)MWO.3OX&%M9&SB-'*2E7E[<G\W*& +MJ`@(*/;>.E.??W^Y$:T!B>)(^/B8X)#0``A+Z3EYN4F9F:F+5G@8"-X;VS-? +M]VD)*1\.1@8&AN8F?F)/5VDIER=SZR*^MF@(:)9^*F]?9V<_[PGQD2&7_D@X +MN+B@,/!@2`+7N7E)B3FYJ?\>B/@(YJ,O4Z_O)_=WIQJF)AZNZJMZNO.'EW=G +MPW+.#BZ^AO;V!@YKCU\G)Z>/BCHI`8')WX:X2`B(F("`V"A[Z3GY">EIJ;</ +MWH@X:/X+8W-[2S_WJ4<S6HZ^PNJ:$N[Z+Z>'I]MBPOKJPAX&1N9"<U_GWR^[ +MPMZ""8&AZ;^VB"@65GA@('C6$RG)"2FI*1?'KR9HR-82H^\O:\N?]]>'\[*F +MIE(:`J[N>C/?QR<#RAHJ6[OB'L;FCLHC8_OKNJ(N7AK)`6%YUXXHZ"CHF.#@ +MH,B"E[GYR8GI=\=OGB@(*.;"0X\C@W_'%_<?"N9&)DYRVJ+ZHQ\W]V?/>SHB +MTOX&=C;F;BO3ST_O8^HNRHF!(4E'Y@@(Z*C(6*#8"&(7.9E)Z7<G7^^N=HAH +M1@)/9[\#8V_GAW_K)C:&;COOTZ,[\Z>'9S\JCOX^;BY.WJ:^"H_GA__+SL9F +M#[FAF:F;1JCVAC:(F%AXUJ.I24EI=X<GIU,N=N@HADI/7X_CH^^GA]^[/@;F +M+@M#HZOZ*R^GYW\C@NZ.[M+NOGYN"I._SR.2?@LI&:'Y1XXH".BH*`CXF,CF +MWPEY.>F';S-C:C[V**BFPT=7%^=OP[,S:^X&%I8F&N]?'\\O;W_?3_ONYL;F +MCKI[F[LC[W^GOWON)HZ3QZFI!T,NGAZFAA:(2`C6CH\WJ1>W9Z=?OX,BWH8F +MCDJ#,T-C8_,OK[.K,FX.KMHJ:VN+V_/O#Z];ZN("0I*NKO(ZZNHJXNXK5]FA +MF6G[ULA("`A(N'@X%@NIF:&9:2?#*@*.)I8H*&:C1^EIU^>/0_NZ;F86*):F +M^L_G9Z?_O[\/KZL.AK8&GD)+L_/3;T^_[UMC/P=W=V=#;@9V%A865JA6-OZ[ +M)Q>IUT<?$SL*XJ[._H[B"Z]_'W_/,POZ0E)N#DY.[B(KPX\_/\_O\WOJHBX^ +M?KZN(NJ[2[J"S[FA6=FI[J@X>+BXR,AX2!8R=_FAH;GW[T(.3AYFEBC6ABJW +M";E)J><;,@Y>!G8H*!:F*Q]'=[?G?V]#"P(^AD8&7C+;#Y\?/V_STU_WJ:FW +M[R[&UJBHUA96J):&0@\W*>G79R_KHD)RK@[^3L*[#^<'YS_#:L+2$E)NSO[^ +M[LIS?R<G/S-+BGI:LFX^'IX.<MJOZ=G9V3EGLG;(N'AXN/@XB/;Z1PD9&;DI +MI\OR/GZFAL:VAJXS1^D):7</>GZ&!L9&1K:&?EKOAW?7-R?OJK(N3K[^GCYN +M8DM3WT=W5U<WI\,2)O:HJ*A6=L9>$DN_AS=WMV<_@RIB[FZ.#FY2`HI;KT^_ +M#Q/[2F*RL@(BVIK*BZ-S[X_OL[M*PJ[.'@[SMRG)R==_8L:H:&CHZ&CHJ+9N +M+Y>)2<DIAU-*0E(N[DX>IM[N*@\'=Q=WYQ,ZSJ;FYN;FYJ9^$HOOIV=GI\^S +M2PIZ^CJZ^IK:VCKJ.Y,/OT_O@ZIBKHY.3KZ^SHZNXFH;DV^/;U.#NZMJ^AJB +MPG)2TD*::R-SKR_O+Y.3\X/;2ZI*&B*"8B):2ONO_Z<GWV\[0OYF1D;&9J8^ +M+F*J8V^?)V?GGR\;N@*24G)"8AJZJCOC\Z_O+W-;ZSIB,I)R\C*"6OJ*"]M# +M$Y/S,^,;.\LKBLJJ2^.3+Z\#2SKR#OX>'GZ^CBZ2XDI+LP__'Q\_;S.;*[H: +MXL(R<C*"V@KK>V.S<W-#H[NJNJ*"PD("XIJ*B]O#<U-3$T.C>RLZNHHJ2QM; +MF^OZ,NZ.#H[NTK)BHIK*ZQLS+X\/CU,#^ZJZVJ*B6OK*ZFN[&ULC8R,;NZO* +MVF*"@N*:2HHK2_N;6Z.CHUN;RRN*&N*BNNO+(].3@SO*PJ[N;B[R(OH*JNN+ +M.]OCPP,CFPMJ.AK:>DIJ*PL[^WO[^[L+B^NKJRLK*RMKRSL[>_L[BRI*^@IK +MF]M;H[N*&A(.#@Z.4B)*ZCN;NYM;HUO;&WN[BZOJ:NJJZPN;HR.CFTN+:^NK +MJRLKZHI*&EIZ^CJ*JZJ*Z@HZN@H*:NL+RSO[2TN[2TN[2PL+B^NJJBHJ*JNK +MJROKZRNJRLIJRDH*R@H*RDI*R@H*:NJJJRN+R[O[F]O;&YM[N\MKZRNJJNIJ +M*BHJZNIJ"LK*"@H*:JKK:VOKZRLJBLHZ^CJZ2DJ**JOK"TL[FQNC6UMC6[O+ +MJXK*RDI*RFHK:PO+NTO+:RK*NII:6EK:FOHZN@IJZBN+"TM+N[O+R\M+2\O+ +M2TM+"XOKZVMKZ^OKZRNKJNIJ"@J*:FIJ:FJ*BHIJ:LIJZROKBVOK*ZNJJRNK +MJBJKZXO+2[N[NTL+B^NKJZHJJJJJ*NJJZTL+*BMJ&GIZXEIJBNK+2RN[.VN+ +M.\L+N\LK*RN*:NKJZNLKZVN+B\M+.\OKJVJ*"KJZ2LJ*ZBJJ*RLKJZHJJJNK +M*^OKZVMKZRNKJZLJB@H*BFHJJJMK"\M+2[M+2\N+:^LK*ZNKJBHJ*FIJ:NKJ +M:FH*:NKJZNKJ*BK*BBHJ*JHKZXO+NSL[.TM+RPL+"XMK*ZNJJRIJ:HH*"HIJ +MBHJ*:FIJZBJJJBJJ*JKKZ^OKZXN+:^OK:^LK*ZNK*ZNKJJLKJZNJJNHJZNIJ +MZFLKJXOKZRNK*BJJ*JJKJJJKJRLKJZNJJJHJJZLKZRLKZRLK*^OKZ^LK*ZHJ +MZFIJ:NHJ*JJK*ZNK*ZNKJZLK*RLK*RLK*RNJ*BJJ*^OKJRNK:BJKJJLK*RLK +M*^OKZVMK:^OK*ZJJZNIJ:BHJ*JJKJZLK*^MK:VOKZZNJ*NIJ*JJKJ^OKZ^LK +MJZHJ*NHJ*JJJJROKZ^LK*RNJJBHJZBHJ*BL+*ZHKJZNKJZNK*RLKZ^OK*RNJ +MJBHJ*JNKJZLKJROK:VLKJJHJZNHJJJLKZ^OK*ZLKJRHJ*BHJ*BJJ*NKJZJHJ +MJJMK:VMKZ^LK*ZLJ*BJJ*HJJ:ROK:VMKZ^MK:RNJ*NKJZBJK*^OKZRNJZNIJ +M:FIJZNJJ*VMK:VMK:^LKJRHJJJNJJJHJ*BJJJJJJJZNKZ^NKJBJKJZNK*^OK +MZVOK*ZOKR^LKZZHJZFH*RLIJ:BHJJJJK*^LKZRN+"\L+:^OKZ^LKZ^LK*ZNJ +MJBIJ"@H*BHIJZJHKZVN+"XMKZZNJ*JJJ*VMKBVOK:ROKZZKJ:HH*BLHZRNKJ +M*VN+BVOKBXN+B^OKZZNKJBHJZNHJ*JJJJRLK*ZLK*ZJJJJJJJZNK*RLK*^LK +MJZJJ*JJK*RLK*ZJJJJHK*ZNK*ZLKJJHJZNHJ*BHJ*\OK:PMK*RNKJBHJJJHJ +M*BJJJJJJJJJJJJJK*ROK*RNKJJJJ*RLK*RLKZ^OK*RNKJBHJ:NKJJJLK*ZNK +M*ROK*ZNK*RNK*^OKJROKZRNKJZLJ"BHJZBJJ*JJJJZJJJZLK*ROK*RLK*ZNJ +MJRNK*RNKJZLKJBHJ*BKJJJJKJZJK*ROK*ZLKJZLK*ROKZ^OKJRHJZFKJ*BHJ +MJJJK*ROK:^OK*XM+*ZNKJJJJJJNKJZNKJRJJJJNKJJNJJJLKZ^OK*ZNJ*NKJ +MZFHJJZJJJJNKJRLKJRNK*ZNKJROKZ^OKZRLKJZJJ*JJJ*^OK*RNK*ZJJJJLK +M*FHKZROK:^OK*ZHJZNKJ*BHJ*JJKJZLKJZJJ*NKJ:BKJ*JJK:XL+RPO+B^NK +M*NHJ*BHJJJNJJJHJJJNKJZNKJZJJ*BJJ*BJJJZNJ*^MKBVO+.XMKZZKJ:HJ* +MBFIJZBHJJJNK*RLKZ^MK:^OK*RNJJJJK*RLKZROKZRNJ*NIJBHJ*ZBJJJJJJ +MJJJJJRLKZVOKZROKZVMK*RNKJRHJ*JJK*^J*JZLJJRLK:XL+"PMK*ZLJZNIJ +M:FIJZBJK*^OK*ZLJ*NKJ:NHJJBMK:XN+BXN+B^OKZZNJ*NHJ*NIJZBHJJBNJ +M*JJJJJJJJJJKJZNKJZNK:PLK:XMKBXMKZRNKJBKJ:FKJ*NKJ*JJJJJNK*RNK +MJZNK*ZNJJZLKZROKBPL+:^LKJZKJ:HJ*:FKJZNJJJRLK*ZNKJJJJJROK:VOK +MZ^OKZRMJRNIJBBHJ*JHK*RNKJJNKJZNK*RLKJZNK*RLK*ROKZVMKZRNJ*NJ* +M"@IJ*JHKB\L+:^LKJJHJZJHKZ^OKZ^OKJ^J*"@IJ:BJJJJNKJRNJZBOK*JJJ +MZJJK*VN+RPN+:^LKJZLJZNHJ*NJJJRLKJRLKJRNKJZJKJRLK*^LK*ZNJJBHJ +M*NHJJJLK:XN+:PN+B^LKJNIJ:FIJ:FKJ:NHJJJOKJJJ+ZVL+"PL+"VMK*ZHJ +MZHH*RLK*BFHJJBLK*ZNKJZNK*^MKZVN+"PL+B^NKJBJJJNHJ*NHJZNKJZBHJ +MJJJK*ZLK*RNK*RNK*^OK:VMK*RMK:RJJ*HK*R@J*:BJJ*VN+:XN+:^OKJZLK +M*RLK*ZNKJNKJZBHJJJNJJZJJJJNKJBJJJZNKJJMKBVLKJZOK:VLKJZNKJRHJ +MJ^OK*ZJJ*JJK*LH*JFJ**JLK*ZJKJJOK*^OKBXN+ZRLK*RHJB@J*ZBJKJZNJ +M*NIJZJKK:VMK"PN+Z^OK*RLK*RLK*RNJJZNKJJKJ*JJJ*NIJZBHJZNHJJJHK +M2_O+2POK*RIJ:HIJZJHKJZHJ*JNKJZJJJROKZROK:VOK*ZJJJJLKZRNKJJHJ +M*NKJJJJJJJJJJJJK*VL+RPMK*RLKJZJKZ^LK*ZNJJRLKJZJ*:JKJZJLKZVOK +MJZJJJJLK*ZNJ*FKJ*JJKJZNKJ^LKZ^LK*RLKJZJJ*NHJ*BHJ*JJJ*^MK:^NK +M*RLK*RNKJZJJJJLKZVOK*ZLJ*BKJ*JKJZNOK*BNKJRLK*RLKJZLKZ^OK*ZNJ +MJZLKJZNKJZNKJJJKJJHJZNHJJZNK*ZNKJZJJJROK*RHJ*BHJJJLK*ZNJ*JHK +MZ^LK*RNKJNKJ*JNKJRNKBNKKJZMK:RNJJJJJJROK:VOK*ZNKJRLKJZLJ*NIJ +M:FKJ*JJKJROK*RNK*ZJJ*VMK:^OK*RLKBZL*BHI*J@NJZJO+NVKB>OO+JRN[ +MVPJ*>P.+6J)**\K*B]O[FOH[N[MJ^LK*6OKJJLN[XP.[JXL[6TMJ:JOJ&B*: +MRLIJ:JJJ*NKJBDKJ"]MCHYO[BZHJBNKJZNJ+ZRKJ"BJKN\OJZLK*"MJ*:ZLJ +MB_L+Z^KJ*NJJ"TMKZNHK*ZN+R[L[*^KJZHJZRBJKJ@K**JJK*BJKBSMKB^LK +M:RNKJVOKJFK*:NHKB^NK:NKKZZHJ:HHJJJJKZROKRPL[FTN+*^LKJXJZ^CK* +MZJJ**^OK*RIK:RLJJJLJJZIJJZOK2PMKR[M+:XMKJVJZ"HH*.LK*"JOK"TN+ +MBXLK*ZHKJVJJJBJJ*JJJ*JKKR^N*BBJKZXNKJBLKJFIJZJLKJRLKZ^NKJZLJ +MJZNJJBMK*RLK*VOK:^MKBXOKJJJJZNJJJBHJ*JJJ*BHJJBHJ*NJJ*PO+"PM+ +MR^LKJJHJZNIJJVLK:NHJZBHJ*JHJZBHK*ZOKZRLK*RNK:NJK:RNJ*RNK*NHJ +MZFH*8NZ26DKK.]OC8P,#@V,C6QM[.TN+ZZNJZFJ*"LK*2DI*2DK*RLK*"HJ* +M:NHJ*JJKJRLK*^OKZ^OK:^OKZ^OKZ^LK*RLK*ZNKJZNKJZNKJZNJJJJJJJNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNK________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +:____________________________________ +` +end diff --git a/share/isdn/1.g711a.uu b/share/isdn/1.g711a.uu new file mode 100644 index 0000000..2ce0200 --- /dev/null +++ b/share/isdn/1.g711a.uu @@ -0,0 +1,322 @@ +begin 644 1.g711a +MJNKJ*JJKJJLJZBHJJBHJJJJK*ROK:XMKZVMK:RNJ*BKJZFKJZJHK*RNK*ZOK +MZZNKJZNKJZMJJFNK*XN+ZRLK*NKJZBJJJZNKZ^OKZZLJ:FKJ*JJKZ^NKJJJJ +MJJJJJJLKZRNK*JHK*ZLK*ROK*RLKZXMKZRNKJBLKJRNKJZJJJJHKZRNKJJNJ +MZNMKJZNJ*NKJZFKJ*JLKZ^LK*ZKJZNKJ*JJKJJJKJ^MKBXMK:VMKZZNJJBIJ +M:FIJZBJJ*^OK:VNKJZJJJJNKJJJJJJNJJRLKZVMKZ^LK*JHKZBJKJJNKJZLK +M*RNKJJNKJBIJZNHJJ^MK:^NKJJNK*ZNJ*^MKB^NK*FJ*BFHJJ^MKBXN+:^OK +MJRHJZBHJJBLK*^OK*ZLKJZNJ:NHJJZNK:LIJ*JHK:XN+:VLKJRNKJJNJJZNJ +MJRNK*RNJZHIJZBJJJJNJ*^OKBPN+BVOK*ZLK:^OKJZIJBHH*:NJJJBJJJZJJ +MJJJJJBLK*^MK:^MKZRN+BZNKJRHJJJNJJJJJJRLK*RNKJJOK:^LKJBIJBHJ* +MBNHJJJOKB[L[N\N+ZZHJ*NKJZFIJZBJJ*^LK*ZLJ*NKJ*JNJJJJJ*VMK:RNK +M*JJJJNIJ*RLKZVN+B^NKJJJK*^LKJZHJ:HIJZBJJ*RLK*VOK:XMKZRNJJNIJ +M:NHJJJJJZBHJJJNK*ZNJJZNKJZNJJJOK:VMK:RNKJBKJZBHJZHJ*JBNJZXN+ +MRTO+"XMK*ZNJ*JJK*NKJ:NKJJNLK*ZNJJJNKJRKJZNJJZPO+2TN+*ZJJ*FJ* +MRDK*BNJJZ^MK:VNKJJJJJJJKJJJJJJOK:VMK:ROJ:JJJJJHJ*JJJ*ZLK:XN+ +MZVN+"PMKJNKJ*JJKJZIJBFHJJBOKJRJ*BHKJJ^OK*RLKJJJKJJLJJBNKJFNK +MBVLK:RMK*RJJ*JMK:VLKJBIJ:JLKJBNK*BHJ*JOKZVN+B^OJ:NIJZBIJZFHJ +MJZMKBXN+:^LJZNIJJBHJ*BJKZRMK:XN+BXMKZRNKJRLK*RNKJZNK*FIJBFIJ +MZBHJJJJJJRLKZBKK*^N+ZZLK*RNKJZLJ:NHJJROKZ^LKJZLK*RMKZZHJZFIJ +MJJJJJZJJ*RMKBXN+:RLKJRKJ*JHKZ^NKJBIJ:FJ*:FHJJZLK*^MK"PL+BXL+ +MBRLKJRHJ:@J*ZNHJJBHJJJOKZ^NK*BHJJBMK:^OKZRNKJZLKJZHJ*JNKJZHJ +M*BJJJJKJ:NHJ*JOKBPO+RPMKZRNJ*NHJ*BJJJZNJZNJJJ@H*:@H*:BHK:XN+ +M:^MKBXL+RPL+B^OK*ZHJ*NIJZJHJJZNJ*HJ*B@J*:NHJJBMK"\L+"XOKZZHJ +MJJJKJZNKJJNKJBLK*ZNKJFH*"BNJ^@KK*VO+"PN[NXLK*RMKB^LJZFKJZBKJ +M:BHJ*BJJ*JI+*XJ+*NHK*BJJ*RNJ:VOKBVNKJZNJJNIJ:NHJJRLK*ROKZZNK +MJZJJJJJJJBOKZVOKZ^LJJJLJ*BHJJJHJ*BJK*^OKZVOKZRNKJZHJ*BKJJZJK +MJZNKJJJJJJNJ*BJKZRNK*FIJ:NJJ*VN+:^NKJJNKZRNJ*BHJJRLKZRLKJZLK +M*^LK*XNKZNKJZNHJJJHKJRMK:VOKJZNJJJJK*ROK:^OKZRLKJJKJZHH*"HJ* +M:NHJ*JJK*VL+"TN[2PN+ZROJ:FIJZJHK*ZNJ*BHJ*BHJJJJJJJNK*JMK*XMK +MBPL+:RNJ*FIJ:NJJJJJJJJLK*RLK*ZNJJJNJJNHJ*JJK*^MK:VOK*^NK*BHJ +MJBIJ:BJK*^OKZ^OKZRLJZFIJ:NHJJBOKBVMKZVM+"^OKJBHJZBHJ*BHJ*JNK +MJZHJZNKJZNHJ*JLK:PO+"TO[2ZHJ:VLK:ZO*2FIJ:FH*N@HJJZNK*ROK"PN+ +M:^LKZVMKZZNJ*JJK*ZNKJNIJROH*BHJK:XO+BVMKZ^LKJRLKJJHJ*JHKZRNK +MJZJJJBHJZJOKZ^LKJZJJJZNKJZLK:XN+:^LKJRHJ*BHJZNKJ:NHJ*BJKJZHJ +M*BKJZNJJJJHKRXN+RPL+"PN+ZZNJ*NIJ:FKJJNOK*ZLK*ZNK*BKJZBJJ*ROK +MZXN+:VOK*RLK*ZNKJJKJ:NKJZBHJJRLKZZNJJJHJ*NIJZJNK*^MKZ^MK:RLJ +MZVLKZRNKJZJJJJNJJJKJZBJJJJHJZFKJJJNK*ROK:^MKZ^OK*ZNKJRLKJZLJ +M*NKJ:FIJZBHJ*BHKZVMKBXMKB^LK:^OK*ZNJJJJK*RLJJJOJZJHJ*BKJZNKJ +M*JJKJRMK:^LK*RNK*RNKJZNK*^OKZ^LK*FIJ"LK*"HIJZJMK"PL+RTO+"XOK +M*ZNJZFHJJZNK*RNK*ZNK*NIJ:HJ*:NIJ:NN+ZXL+"PO+2\N+ZRLJ:FKJZNHJ +M*JJJ*NKJ:FIJ:NJJJZLK*^N+BPL+"XN+:^NK*NKJZBHJ*BKJJJLK:RNJZNKJ +MZJJKJROK*ZLKJROK*XL+Z^OKZZLJ:FIJBNHJZNKJJBMKBVMKZROK*ZNKJJJJ +MJZNKZ^OKZRNK*NKJZBHJ*BJJJ^OKZVMKZZLJZNJJJ^OKZ^LK*ZNK*ZLK:VMK +M*ZHJBKK*RLIJ*BHJJROKBVN+B^OK:VMKZROK:^LK*ZNK*RNK*BKJBHJ*"LH* +M"HKJJVL+2\L+:^NKJJHKZRLK*RLKJZNJJZNK*RNKJNIJ:FIJ:HJJBRMK"PO+ +MBVNKJBHJJZJJJBHJJBLKZVLKJJHJZFKJ*BHJJJNK*^L+R\M+RVLKJBJ*BFKJ +M*JJKJRLKJJJK*NIJBHH*BFJJJVN+BXN+BPL+"^LK:RNKJZNK*ZNK*RLKJRIJ +M:FKJZBHJJJJK*ZLJ*NJJ*BOKZVN+BXL+BVOKJ^J*"@K*"HJ*:JJK*RMKBVMK +MZROK*RNK*ZNKJZNKJZLKJZHJJZMJZBHJZBJJJJMK"PN+BXMK:^OK*RHJZBHJ +M*JHK*RNKJJHJ:LK*RHKJ*BMK"PL+"PL+B^LK*ZNKJBKJZBJJ*VN+:^NKZFIJ +MZBJJ*BHJ*NJ*:JLKZXL+BXOK*ZJJJ^MK:RNKJJJK*RLK*ZHJZFIJ:HJ*:BJJ +M*VL+RPN+Z^LKJJNKJZJJJZNKJBHJ:FKJ*JJJJBOKZXN+BXN+ZZNK*^OK*VMK +M*BIJBNHJ*NJ*BFKJ*BJKZROK*ZNJJ^N+BXMKZRNJJBHJJJJKJZHK*ZNKJZNJ +MJZNJJJJKJZNJ*JJKJJLKJRNKJZJJJ^OK:VMKZ^LKZRNK:HKJ"@IJZNJ*ZBJJ +M*^N+BVOK*ZJJJBMKB\L+:RLK*^LK*ZKJ:HJ*BFKJ*JHJZJJK:\O+RPN+Z^OK +M:RLJZNKJZNKJZJJK*^LK*ZHJZFHJZNHK*ZMKBXN+BVLKJZJKJJLKJZHJ*NKJ +MZNKJJJJKJZLKJJNK*ROKZXMKBVOKZRLK*ZKJ:NHJJPN[.TOK"IKB`N*:ZLL; +M(Z/[BZIJBNKK2WM[.ZMJBKK*:JMK"\L+*VI*NDI*"FJJJRNKZNHJJNN+R\L+ +M:^LK*ROK:VN+B^LK*NIJ:FIJZJHKJZKJ:FKJ*JOKBVLKJZNJ*BJJJ^OKZ^MK +MB^LK:ZN*:HJ*:JHKZXO+2\L+:VOK*RNJZNIJZNJJ*BHJJJJKJBKJBHJ*:FIJ +MZBJK*ROK:^NKJRLK*RLK*^MKBXO+R\L+"PL+BXOK*RLKJZJK*ZOJ:NIJ:FH* +MRKKZ.CHZ^OKZRFJJZXL+R\O+RTM+2[N[N\O+RTN[^YO;HR,CHR.C&[MK:OIB +MDNX.SDX.[E+"&LHJ:\N[>QM;H^,CVQM[N[L[&V,#`T/#0[,S<R]OCV\O`ZO" +MSJ8&1D;&9AX.\IJJN]L#DR]OCX_OTT/;2ZH*2DJ**SLCLQ.OKW,#(UO;VZ.C +M&TMJ8BX^7B;F)EX^[H*ZZWM;HX.S0_-SDY/S`R.;.TO+"\L[&Z/C8^-;6]O; +M6R,C6SNK>C*.?J8FYJ:>SA):ZCOC,Y-3KU-3D_-#@R.;2^NKJJMKNYNC(^-C +M8^,CXV/C6YM+"H*N3MZF)B9>_HYR6FJ[(_.O+^_O[Z^3PZ.;R^NK*BHKRWNC +M8P/#L_,SDZ]3DT,;*F)NGN8&QL:&)O[N8NK[`Q/OC\_/SP]O4T,C.VNK:KJ* +MJNM+FZ.#`V/C8V/#,_-S0Z-K&J[^)@;&Q@;FGFYBJEMS[P]/3\_/;R\3PUN[ +M*XKZFOK*JLM[V^/#0[,#X]N[ZRH*NGJ:VEKB@D(RDM*2PD)"XEJ:2FJK:TN; +MVUM;VYO[^WN;F_O[>WN;FWM[>SL[.[O+RXOKJRJ*:NHKNUL#0T-C2\K";GZF +M)B:F'L[2VBM;\R^/#X_O4S,#H_L+ZRH*BFIJ*\L[&Z/C@P.#(]N[Z^K*N@KJ +M:_NC@X-;2XIB+CY>YF;FIGYN@BH;<^\/SP^/[Z^3,\,#(]O[BRI*FJ+B`@+B +MVCJJ2QN#L_/SLV/;.PMJNGJB(GH*:]LS4Z\O$R/K(FZ>)H8&AB:>CD**>S/O +MS[___[_/CZ]SXSLKRMK"\A*2,L):BLM;LZ_O[R\SVZI:(GJJHP\G!T='Y^]* +M_C;HR$A(""BV?KJOI\?W=W<WQ^??/\]OK],S([MJXBY.'B;F)E[^[F*JX^]/ +M_W__SR^S&RM*H@(R\C*R`J+:^DH*BBHK:\N[^QM;HZ,;.\LK:FIJ.OK*BBHK +M:XO+2TL+:^NK*FH*"HIJ:NHJJJNJ*HJ*B@H*:BKK"TM+N[M+RPN+:VOK:RNK +MJNKJZFIJ:NIJZNIJBHH*BHKJJJLK:PO+R\O+:ZOKJNHJZFKJZBJJZXL+NSN[ +M2\O+"\N+ZZNK*NJ*BLK*"FHJ*JJK*^OK*RLKZ^MK"[O[^[N+JPIZ(K)2+HZ. +MCN[RHFI[0Z\/O[^_3X]3PQN[Z[I:@O(20DK[K]\'-_<WAT\+CL:HB$BX2(BH +MQ@XKC^>WEQ<7E_>WQV<GGT^OVXJ2?H;V5B@HJ/;F+DN_!Y>IJ=<W9\_[0OYF +MML8F+ONG%VG)R6EW_R+&:/@86!@XB'9^ZH_GM_=W-T<'AP<'Q[='!R>/ZXX& +MUF@(R(BHQHZ;WS>IZ>DI%\??$RM"#AXFYF;FYB:F_N[:(__'5VD)"6G7YWN> +M%@CX&!AX2.BVCAM?-ZEIB6GIJ7<'?S-*;B9&=A;6=L9><ON_AW=7J:D7MZ=3 +MBFXF-M8HZ.BH!FYC-XGYV5EY"4=;YFCX6""@&+@HAI);?\=W5RGI:8F):2F7 +MYX/N1NA(^/BXB/:^6^?7:0D)B2GWYR^KKJ9&%BAHJ`8.0Y<)>:'9.2G_;BAX +MH&!@(!C(]@X[_P=W%]>IZ6D)2<D)Z3</4C8(>%A8&$A6WCLGE^EI:>FIE\>G +M;[O"_@:6*&B(%IX+E_FA88$AN8>.B"``0+``(#@6[O/G-]>IJ>F)R3F9F?G) +M%^\^*'@@X.!82';N4\>IZ6EI*5=W1R>_@UK^QE9H",C(%F(?"6'!L3%A.3]V +M&,!P<'!`(+B64D,G1Q?IB;D9H2$AH?DISWYHV."`8*`XUFY3QU?I:6GI*5>7 +M1Z>ORIZVJ(C(2`AHECKW28%Q<7%!F6=VH+!0K-"0`)BH;B]'*8GY6:'A@>$A +M&>F?/NC88`"`X'@H/N_WZ<E)20GI5T<?K\H.)K;6J"@HJ':&7CZC*9EAD=%Q +M,9F/:$#0[(RL$`"(GG\IR9D96>'AX6&A.5?CQC@@@,!@&(A^OY<)N;G)Z=>' +M[]M:/EYFQ@9F'D[2^MIB6K(.)C+7N2%1T3&Q*6;@+.P,C'``R(^W"3E)>3F9 +M8>'AX0D?ICC@P``@>`83!VE)"0FIEX>O`Y(&MJ@H-EYJOP<71Q\3C@8V5G9V +MECK)H4'MK3&!N_B0C(P,[&`8_A=7.3D98>'!L>%Y1S88P+#`8&@N#VE)R4F) +MZ5<'GQ+VZ/AX:+9+-PGYR2E?CD8H"(AHR*B7@4&-3=$Q_V`L?#Q,#"`&V]D9 +M(>&AL4&!0;G2N/"LK##H@QDQ08$9QULF)AX6EFC8^,C&I[EA`>'Y/T8(V!@X +M"*BHEA;HMRW-?>6]X<:\)`2$O*P&D9&M4<&Q(0'QR;,X[+S\#."'+7T]37$? +M.##PL&#H:&AFIE]Y`7%!H0>(((!@R&8C/RJZ?B9K,Z=AS<WMS0D`[*3<W,Q* +MI\&-L;&A%\D.&N8P,!!0&)NQ#0U-D:=HT"R0P,;;J9FI"2GGEX.N-CAHZ/Y' +M]VD7*HZHJ`8FHP+V`O$]S9W-J-`DA"1<<O'1'>UY=\C&B&CBP/"PD*AY+?U- +M;=D@$`SL(%Z9X2'9)Y\#CKMFJ(@X1D)W>6G7&Y86*#;>_J+FJ-89'=U]?2[, +MY+2DO&H];4VM?I;8%C+H7L`LL"!?T0U-+2':P$#`X$;^C^>W>;G9":ZH(."X +MQC>)28DC@@Z>2LX&:'@(=F*74:6ES9'`W&1DC&!A3='Q::CHJ*\F.%C0\'C_ +M0:TML:DK!IX+CI888)@>^3&1P;_8,'#8(LE9B=]>]CX;YT^2]@C(%JXCZNG- +M)?V-*<RDA)Q`2LWM03D(N$B[AZ@(,-`@YJ&143&)_T(ZI^X(X,#X$P&M$2'F +M0-`PJ*GA(3=^2,A^9\E7RR@8.!8#=\=B3XW=S>WNS*1D+$A93;&9B(#XZ'D7 +MGLC00/C?P;'Q.0=W3V<N.``P>'_!+9'YUK"0@(ZY(3EKJ,BV?RF)IQ[H2):> +MZ\]KQM(MI9UM3KPDY*PJ`6VA6F#@9F<!:5;`+,"V>4&!H6?'R0FI!F"0L";9 +MK:WA[H`PX*9I>2FNB,@FQ\D)9_XH:':^(INSZY*V$JVE?:W63%Q<``<AL9-H +M@`@'.<'?F/!0V#NA(4DIXZFA(4EFX'"`ZR$1L:EH`.`HOPGISW9(Z+(WZ1>_ +M2L[FME96ADIGQ\/N(7T=#6DL_*3L#E<!YQ:@F$<)`>E(0*R`)@DAR0D':>$A +M:5:`L-BW8?'AKTA@2+)7B5\^R+BV+RDI1\LFAN8./E[>#B._@XZ)3=U-83"\ +MW`SVW]FG*)B8QPGAB8B`$(!&=SD7Z1>Y`8&Y-F"P(#^A0:%OZ!BHZ]<I4Z8( +M"#:[U^D7TSZVMJ9^?J:.0U_/[O^M'7T1.,P</)BGN??H&%CO2:'Y%F!PP)8' +MN7?W*?FQP0EHL#!8Y^'!V:,H2,8/=T>ZAE:6OMOGAR=/F_*&%JBVRB=G2T;Z +MK5V=T:"\G$SVZ3GCX(`@5^$!^4A`$&!^5SF?)RE9\<&I^##`B&GA(=?FUK:/ +MJ7>CJ`B(AL.'U\=_H^IBAJ@(%AI_=Y<W@<W-T4ZLC,P@"J>/"+B8`TFY"18@ +MP.!VKXDWMVDY8>'I!J!8*&?)">?>AL[?5T<[%HCHALO?!U^_`VNJ[GXF)OXN +M8HX.6;W=S6D03+RP:F>KV&"@*Z$A>=X@P(`HNH>/[VDA,;&Y1H!@B(>9N2<& +M%MX_*:G/AB@H-NXJLT^G)U_3OO8HEM)/)_.)[?W-(6!L#/`N0Y)8`*`^&:'Y +MPJ```,C.IV<?:9EAX0E#EA:F\T<?Z^9F`C_W!V_N9F8&9F9^HF_'YV_J;E[> +MXCM+SJ9IC1V]6;`,#$`;6S8`0)A382$))J#@((@&P@J/^6%!X:D2Z%;^#P=O +M2IZ.&S_GOR/R/E[&MD;.[Q<IYW(6Z#::WZ=*1M*QG1TM=FS,+/;?/J!P(`:9 +MX0G[>*!8");&+B*IX4$!2:\V%O[JWR\JHF)3OQ_OBUJ^SN8V=F:J)U>7#XZ6 +MU@;:SV_R-BG-73UYD,R,(/\Z.'"P"-=A^6>HF/BX:(CV/N<AP<&9IS*^^V,# +MJXYBNF/OKV^S<\K.YI86MJYO1V<[[A[.\KL3^N96^G$=W:TH;&R0)O.(`'"8 +MBWD9YQ*(B&A(N#@VX[D!`2%IGWIN,A**ZGO3FZ/+&^\/+W*F-JB6'A/'=U\Z +M?B:^2GL"QBCCK5T=<=AL[,!B,MAPD$BG(?G/IFA6J$@8>$9_H4&!&3>_DR^# +MKB[..K.;R_H;3R=_<L8HZ/8.KZ?GCVHBXJOK(BYFUJ^M'?U!V"Q0X)K.(/`P +M"%_YB0-.=D;6.-@X9F=9`2&Y!P^GQZ?:WJ:N(QM*XJM/9Z>*YA8H-LX++X_O +M0[L*`BY2TJ8VGRT=/8$8K!"@#L:`<$`HQSEI,Z[F9A;X()CVG]D!X0E_JD_I +MN1=:5JBF*H/K"C,G!R^^%JC&CLK+:Z*RXMH:FNMC2E[>^<T=C7<`T+#(!GA` +M,"#"5XD'PKXFIJCXV#AF!]EAH6DGC\?IZ5\.=G;^:X-+>V^G)P/^EJ@VGH)J +M"OJJXX-[.VNB+HZ2Z2V];?F(``"8:)C`0.!6?[<WSRONOH8(.$B6NVD9V;GI +ME_?WY^]Z_B:>DKH[@\__SR-RYG;V!@[*JDH:VIJK@Y,;>N[NU]%-[9E&6&"8 +M")@`P.#(.I]')Y,:PJYV*.@H)G_IR4EIZ>GIER<S<CZFWCXN0NKS+S^ONJ9& +MQJ8B*OHRKG*Z>UL;8Y/;[_F1K8$W&I:(:+@@X*"@R`9.(T-+RJ,[2HL2/A([ +ML[_G!Q>I%[?')T\3*B*B"KJZ^CK+JV*.OK[2VD*NCO[^[G+":OL#$Y,OEUD9 +M)Y]W)V_34@:FQE;V=JAVUF@H!B8NBRIJPX_OCT\_I]]_I]\?WQ^/3]_??\\# +MJOJ2/MZ>O@Z^IJ9^CF[N,AH*"[NK+PE9]W_IZ9='/R[NCC9V=NCHZ,A(UL9F +M$N*">S^_[X]O/^?G)X<'Y^=?_W\?GW\O*QK"3M[>'GX^IN:>S@[N4E(:"VNJ +M:RLOB7EG)TD)5[?O[AK"QG96B.@H"`C6]@82VCI#3]/#\Z]_9^<G)^=G9]\_ +MIV>G3^.JRF*.GEY>'MZF7GY.SHZNHNL[FQM+BSO;I\F)/Q<)J;?GBV[:?K:V +M5F@HB,CH1H:^HB+*$V^ST^\/I^>GIR>G)R>??Z>G?^^;ZZH"3G[^_DX^IJ8^ +M#L[.+H)Z2JI+"\L+NP>YJ;\IR5='WYI"*IZV-J@H%BB(5L;&3B)B*A.S2Z/S +M;Z>G_Q\G)^<G?Y\G)U]/8XLK&NX^?G[^'B8F7AY^#E+"F@HJB[L;8UL[LQ=) +MA[]IB1<';T(*ZUY&]BBHUNAH=L;&/G)"BR_CRX.O3Z=??Z=G9^<GWZ?G)W]O +MH^OJ@LY^?IZ>'J:F'OX^#B[R6FHKJPM;\S-[:Q^):>_'">DW)SMRZ\)F1A8H +MUE9H*#:V9FX2HEMS>]OS[]_GIZ=G!X>'7W^G)]]/`\L+.BX.SGY>IB8F7EZF +M'DXNPIHZ"LO#D_-3[V^O;T>)MT]7:?=?+V(".IY&]E:HUBB(J#:VWG+:"],S +M@Z]/7V?GYX>'YR???Y_??T\O&^KZ$DY^'EY>IB8F7J9^;I*BJ@M+HX.S[X]3 +M\W//ERF_?RDI!S^;DOI"9K;VUA86Z"CVQF:.0AK[DP,S[S\G9R>GYV?GI[\/ +M_W\/+V.+ZAJN3OZ>?AZFIMX>GD[N\AIJ"SN;PR_O[X_OTQ]7UZ^G5W<GC^I2 +MVNYFQO86-G8H5D8&IM*BBF/3LW/OOR?GIR>'A^<?#V_/SR^#BVHZ@NX^_G[^ +M_MX>/KX^CC*B2BKKF_-SLQ.O<_.O9ZEG;S?7Q__SXB+Z_H9&EI8VUJ@VAN:. +MHKI+<T.S+X\_IU^?7R<G7S\/S[^/$Z,K2IKR3OZ>GI[>7IZ^#FY28LIK"TL; +M@_/3DQ,OWT<'IV='!Z=O2\H:+AYF1K:V]I8V!N;^KF+J>]NC\Z\/?]^GIU]? +M)U^_CX_OT\-+BOKBDB[.?AZ>WAY^/LXN<N+**[O;@W.OTU-_1[=?YS>W)\]; +MBLJ"OJ:&QL9&]K:&YI[NPCKK>YM;PU,/S\\_7Z>?GQ^??S]O<\.["MHR[@Z^ +M?A[>WG[.#FYRXGKJ:WL#\]/OCP\_WU\??W\_CY-;:PJBDNZ^'EZF)J;>GK[N +M$@)Z"JH+^UO#,Y,O;V^/#\\/CV\O<V-[:RJZFMHB@H*"@@)"`F)B8LI;$R-[ +M;\\O8[NKJVOZ@K(2TE)NCE+"`II*BBHKZFHKRYNCV]NC8X,#`X-#,[,SPX-C +M8Z-[N^LJ"AKB@L(R<I)R<O("`N*B6IHZ"BIK2[M[8^,CPP/#0[-#PP,#8]O[ +M^TMKJHI*.AJB8L)"PD)"PN(BFDH*:BKKR_L;6R/C8^,;^POKZHK*2DI*2@IJ +M*FO+NSM[^SM+ZZNKJZNK*ZJKRPOJZSO+"\MKZVLJBLHZ&MHB@B):(J+:FOI* +MZJN+.YO;V]L;&]N;>WO[NTM+"PM+2[O[.[N["ZHJ*HJZ^MJBVMI:&OHZ^KK* +MBBHK:PO+R\O+BPMKJZNKJBJJZVN+RPL+RVLK*ZJJ*RNK*JHJJBLK:XOKZ^MK +MBVLKJRNKJZKJBFKJBFIJ:HH*"HJ*BFJKZ^OKZ^N+:^N+"PL+"VMK:^LKZ^NJ +M:JOK*RLKJJOKZZKJZBHJ*JJJZFIJ:HIJZBJJJJJJJBOKZ^OKZ^OKZZNKJRMK +MBVOKZ^OK"TO+:RNK*NIJ:FIJZBJJJRHJ:FJ*"HJ*ZJHJJJN+ZZOK*^MK*RLK +MJZNKZ^N+"\M+"VOKJZJJ*BJJJNIJ:NHJJJOKZXL+B^LKJBHJB@K*2DK*:NIJ +MJBOKBVOKZVMKZ^LK*RLK*RLKJRMKBXN+JVHJJ^KJ*BJJJZNKJJLJZJJK*^LK +MJZNKJBJJ*NJJJJLK*^MKZZNJJJJK*ZNK*RLK*RLJ*BKJ*BJJJJJJZNHJ*^MK +M:VN+"POK*ZNJ*NKJ:FHJZZHJJRIJZNKJ*NKJ*JOKZ^MKBPL+:VMKZZNKJJHJ +M*BKJZBHJJJJJJBKJZNHJJBOKBVN+BVOKZ^NKJZJKJ^OKZRLKJZNJ*NHJ*FJ* +MBNJJ*RNKZVOK:VOK*ZKJ:HJ*ZJJKJZOK:^OK*ZNJ*BKJBFKJJJNKJRMK:VN+ +M"VMK:^OK*ZHJ*NKJZNHJJJJK*RNKZHIJJBNK*ROK:VMK:XMKZ^NK*^LJ*JHJ +M*BHJ*JHJZNKJ:NKJZFKJZJOK:XN+"XN+BVN+:RLK*RLKJBHJZFKJ:HIJZJHJ +MJROK*ZLKJZJKJRMK"\O+B^NKJZJJ*NKJJJLJ*BH*2NJJJJNKJZLK*VMKBXMK +M*RNKJZLKZZNJ*NKJ*BHJ*JJJJJJJ*BJJJJJJ*^MKBXN+:VOK*ZNJJJJJ*NHJ +MJJHJJJLK*ZHJZNJJJJJJJBHJJFO+:XO+:^OKZ^LK*ZNK*RNKJBHJ:HKJZHJ* +MZBJJ*NKJJRLKJZJK*^MKZ^LKZ^N+"XN+:^LKJZJJJZNKJZKJ:FIJ:NKJ*JJJ +MJ^N+RTM+RXN+*@HJZFHJ*BHJJNIJZBJKJRLKJ^OK*ZLKJRLK*ZNK*^MKZZNK +MJRHJ*JJJJJJJJBIJ*BJJJJJK*^MK:VOK*ZJJ*JJKZRLKZRLKJZNKJZNJJBJJ +MJ^JJJ^KJZNJK*RLKZROK:VMK:VOKJZNJJRLK*ZNJ*BKJ:NIJ:FIJZBJK*ROK +MZ^MK:VMK:^LKJRHJZBJJJNOKJZHJ:HH*"HIJ*BJJ*VL+2XMKRPMK:^NKJRJJ +MJJJKJZLJ*BJJJJHKJZHJZNKJ*BJJJJNKJROKZVN+:VN+:^LKJRKJ:NKJJJLJ +M*BHJJRNKJBKJ:FIJZNJJ*XL+"PO+RPN+RXLJJJHJ*NIJZNKJZNKJ*BHJ*BJK +MJJLKJROK:VOKZROKBVMK:RNK*RNKJBLKJZNJ*NKJZFIJZBJK*VOKJRHJJJHJ +MJJNK*^OK:^OK*RNKJBK*2NIJZBHJ*VMK:VLKJZLKJJJKZ^OKZ^LK:VLKJZNK +MJNJ*"@J*:NHJJJLK:VMK:VOKJZJKJBKJ*JJK*^OK:XMKZZNJ*BHJ:HJ*:NKJ +MJJOK*XL+ZXMK*ZJJ*JJJJZNJJZNJ*BJJ*BHJ*JHK*RMKZRLKZRNKZRLK*RLK +MJZOJZBJJJZLKZRLKJZHJJJKJ*BHJJJNKJRLKJZNKJZNKZVMK:^LK:HHJ:FHJ +M*BHJJBLK:XN+ZRNJ*BJJJNHJ*JNKZ^OKZXOK*ZNJJBKJJBHJJJNK*^LKJZJJ +MZFIJZBJKZXL+BVOK*RLK*ZNJ*BKJZNHJ*JNJ*BKK*ZHKJ^HJJZLK*RLKZRLK +M*ROK*ZHJJBHJJJNKZRLKJJJJJBJJ*NIJ:NJJ*^N+BVMKZRLKJZNKJZNK*RNK +M*ROKZ^OK*FIJ:BJJJZNJ*BJJJ^JJZRHJJBJJ*^LK*RLK*^OK*RLK*ZNJJBHJ +MJJNJ*JHJ*JJJJZNKJBJJJJJKJJNK*^OK:^OKZ^LK*RLK*RKJ:NHJJJJJ*BKJ +M*JHKZ^MK:^MKRVNKZRNJ*BKJ:FKJJJNJJZNJJROKZVMKZVLK*^MKBVOKZZHJ +MZHJ*BHIJ:FH*BFHJJ^MKBVOK*RLK*^MK:^OK:^LKZ^LKJZNKJBHJZBHJJZJ* +M:NH*:JJK*VMKZRLK*RLK*RLK*^MK:^LKZRNKJZKJBNHJJBHJ*NKJZNJJJZLK +M*RLKZVMKB^LKJJJJJJJK*RNJJJKJ:FIJ:FIJBFJKZVMKRSO+BPMKZRNKJJHJ +MZNHJJJNJJRLK*ZLJZNKJ:FKJ*NJJJRMK:VMKZVOKZ^OK*RNJ*JHKJZHJ*JJJ +M*NIJZNHJJJOKZVMK:^NJJJJJ*BJJ*JHJ"BJKJJLKZXN+"XN+BXOKJZJKJZNK +M*NKJ:BJJJJNJ*JHJJZJJJJNKJJHJ*JJK:VN+:^LKJZNKJRNKJVLJ2BKJJJNK +MJJOKJRNJ*JNJ*JJJZJN+*ROK*^NK*JLJJROK*VN+:VOK*RLK*RNK*BHJ*BKJ +MZBKJBHJ*:BJK*RMK:PM+"VOKZ^OKZRNKJZLJZBHJ*NHJ*NKJ*JJKJZLJJJLK +M:^MK*^JKZROKZZNKJZJJJRLK*^LKJRNK*RNJ*BKJ:@IJZJMKBXOK*RNKJZNK +MJZNKJRNKJZLK*^LKJZNKJBHJ*FIJ:FIJ*JOK:VNKJJJK*^MK:^N+RRLJJNIJ +MB@IJ:NKJJJJJJZNKJZLKJRLK*VMKZ^MKZVN+"XN+:VOK*RIJ"LI*R@IJ*JLK +MZVOK*RLK*^OKJRLKZ^OK*ZLJJJKJ:NKJZFHJ*RLJZ^LKZVMK:VOK*ZNJ*NKJ +MZBJJJZNKJZNJJJHJZNKJJJJKJRLK*^LK*^OKZVMK:^OKZ^OK*ZHJ*JKJZNIJ +MZJJJJJJJ*JNKJZLJ*NHJJBJJBTO+RTMKZ^NK*NKJZNKJ*JHK:VOK*ZNK*NIJ +MBFKJZNKJ*JHKBXN+BXN+BXN+Z^NJZBJJJJNK*ZLK*BHJ*BHJ*BHJJJJK*ROK +M:XMKZ^NKJBLJBJJJ*JJJJJJJJROKZZNKJNKJ*JJJJRNKJJLKZRLKJBHJJJLK +MZVOK*ZKJ:FIJZNHJ*JHK:PL+"VOKJ^KJ:NJKZVN+BVLKJZNJJJKJBHH*BJKK +MJ^L+:VMK*ZNJ*BHJJJJKJJJJJZLK*^OK*ZNKJJHJ:FIJBFIJ:BJK*BJK*XL+ +MBXN+:^LK*ZJJJ^OKZVOK*ZLJ:NKJJJJJ*HJ*ZBJK*^MK*HJJJJHKZ^OKZ^LK +MJJJJ*JLK*RNK*RLKJRHJ*BHJ*BJJJJJJJROK"XMK*ZNJJJHJJJJJ*JJJJROK +MZ^OK*ZHJ*BHJZNJJJZNK*^OKZRNKJJJ+"ZNKJRKJ*BHJ*NHJJJLKJZNK*NKJ +M*JJK:PN+:VMKZROKJRHJ:NHJJZNKJRHJZFHJJBOKZZLJZJJJJBNKJZNKJROK +M:^OKZZNK*JLKJJHJJHH**NKJJROK:VOKZ^LKJROKZ^LKJJJKJZNK*RLKJRIJ +M:BHJJJJK*RLK*ZNK*^OK*ZJJJJJJJJJJJBJJ*JJJ*BHJ*JJJJBLK*ZJJJZLK +MJZKK2[N+BVNKJZHJJNJJJJJJJJNK*^LKJZHJZFIJZNKJ*BHJJJJKZVN+R\O+ +M2\N+*ZHJ*BHJZFJ*BFKJZJJK*ZNKJZNJJJJJJROK:PL+BXMKBVOJBFK*"HKJ +MZJJJ*VMK:^LKZRLK*ZNKJRNK*^OK:^NKJJJKJBHJ*FJ*B@J*:BJJJBLKZ^MK +MBVMK"PL+"XN+:^OK*ZNKJBKJ:FIJ:NKJ*BKJZBNKZJNJ*JJJJZNK*^OKZRNJ +MJBOKBVMK:VMKBRLKJBHJZFIJ:NIJ:FKJJJLKZRLK*ROK*RLKZ^OK*ZNKJ^MK +M"XN+ZZNJ*BHJZBHJ*BHJ*JNK:FJK*NHJJBLK*^LK*ROKZ^OK*ZNKJZNKJJHJ +MJJJJJZNK*ZLKZ^LK*ROK*RNK*ZHJ*BHJJJHJ*BJKJZNJJJJJJJNJ*RNKJZNK +MJ^MKZVOKJ^L+B^OKJ^IJBHKJZNKJ*NKJZBHJJJJJJZLKZVN+"\O+RPMK*ZNJ +M*NKJZFHJJJNKJNHJ*JJKZRNJJZJJJZLK*^OKZ^OK*ZNKJZJJJZNKJZHJ*HHJ +M*ZOKZZNKJZNKZVN+BXMK*ZLJ:HJ*:FKJ*BHJJJJJJZNJJJHJZNHJJVN+"PL+ +M"VMKZ^OK*^LKJZLJ*JHJZNIJ:FIJ:NIJ:BJKZXL+BVMKRXLKZZNKJZLKJZNK +MJRNKJBKJZBJJ*BHJ*JJJJJJJJRNJJ^OK:VN+ZZLJ:NKJZBJJJZNKJZLKJZJK +MJJJJZFKJ*JLK*^MK:XL+"XMK:^OKZZN*ZBJ*:NKJJBHJJJOKBVLK*ZHJJJLK +MJZLJJJJJJ^OK*RNJJJNKJZNKJJJJJBHJ*BHJ*^LKZRLK*RNJ*JJK*^OKZ^MK +MZRNK*BHJZBKJJJHJ:\L+:VLKJZHJZBKJ*JJJJBJJJROK*^OKZZNKJBJJJZNK +MJZNJJJLJ*BJJJBOKZRLKJZJJJJJJJRNKJBHJJ^LK:VOK:^LK*ZNK*NKJZJHJ +M*BNK*NMKZROKZZLJZNKJJJLKJRNK*RNJJJHJZJHJZBJJJJNK*VMKBXOK*ZNJ +MJBJJJ^LKJZHJJBHJ*BJJJZNKJNKJ*NKJ*JHK*RLK*RLK*RLKJ^O+*ZLK*ZNK +M*JKJZFJ*:FKJJVN+BXMKBXOK*^LKZVMKBVOKJNIJ:NKJ:HH*BFHJJ^MK:^OK +M*ZJJJRLK*^OK*ROKZRNKJZLKJ^KJZFJ*:NHJBDKJJRMKBVMKBXN+ZRLK*ZNJ +MJJJJJZLKZRNKJJHJ*JNJJJLJJBHJZBJKZ^LK*ZNK*^OKZRLK*ZHJ*NJJ*RLK +M*ZJJJBHJ*BHJ*JJJ*^OKZZHKBVMKB^NKJRHJZFKJZJJKJ^OKZVN+:RNJ*NKJ +MZHJ*:NHJ:FJJ*^N+"PL+2\N+"^LK*ZJKJZOK:VOKZZJJ*NHJ:@KJ*NJ*RFHK +M:XMKB^NK:ZIJJ^MKBVLK*JLK:XOKJNIJJFIJ:FJ*"NL#6[)RJU/K)K9[!X/S +M/Q.S?\XV$D=I#]8HBYO/JIY;OJ(CWS]")N9"F]_W!V+>PAZV&AM?Y[,O3^IN +M^^_OT_HNPC*./J8F6@M[P\\/\ZI*DQ/;@DK/,SJ[.ZICC[HF)O(:3OKJ(J?O +MFH,K\NICDT-CD_.BNN,2^F)^,D-3X\*F$N)3_P_O*F,"6JN:KY,/RN[*`H+J +M8G*:"^LJNSMC8T.J.D.;NDJN[IIK*BM+._N[HRJZ^ZH;`YI"Z[MJBK(;VSM; +MBP/JJQK2\B)JLB,OV]N*VKIC,XMKJ^JZVJMZ"EOSJUI:>FNJ:IO[*\K"BPLK +M>XM#$SJ">IKZ.^N+V\JZ@FNC^TOB@OH[FXIJVEHK.^O[RTL;NQLKZCNKZBJB +M>OM[ZYJJ^ZH+ZN)B"[L*"J*:ZH-;>UM+XWIR>LKJRHL+.XMJXYNCVWIZ:ALK +M2KIB2@O+BJN+>GJJ8WMJBOKKJRMJ.QNJJYK*NUOJ&JO*NYNJ6L*[HZ,K`EH: +MZWM[2ZIK*OL+BTO[VVLJBHI*ZLI*RVO*"CKJNGK*JVN;NZL+2]NJ2@KZRNO; +MRVM+2^LJ:OJZ"NOJBBN+ZRLJRCHK*XOK^KHJ2PO[*TL;>YN*2IHJZ\I*&NJK +M2RMKB^LJ.FL[RSJZZHO+ZTM+N\LKRVOKRAI:F@H+:XLJBFNKJZLKR@KJ*NM+ +M^PNJJLLK:XNK*XJ*NBN*.NMK>ZLJZVNKRLJ*2SNJ2RL"#B["FNH+^UOC8X-C +M8R.C&YL[NPN+*ZLJZHJ*RLI*2DI*2LI*RLH*"FIJZNHJ*JNK*ZLK*^OKZ^MK +MZ^OKZROK*^LK*RLKJRNK*ZNKJZNKJZJKJJNJJZJKJJNJJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNK________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________\````````` +M```````````````````````````````````````````````````````````` +:```````````````````````````````````` +` +end diff --git a/share/isdn/2.g711a.uu b/share/isdn/2.g711a.uu new file mode 100644 index 0000000..53e09cc --- /dev/null +++ b/share/isdn/2.g711a.uu @@ -0,0 +1,277 @@ +begin 644 2.g711a +MZ^LKJBKJZBHJJROKZFJKZBHJ*BKJZJJKZXL+R\L+B^LKJZHJ*BKJ:HJ*ZBJJ +MJ^MK:ZMJRLH*BNKJ:BHK:PM+N[N[2PMK*ZNJJJNJJNIJZBJJJZNJJZNJZHJ* +M:FHK:^N+"XN+B^OK*ZJKJZLJZNHJ*BHJZBHJ:FJ*ZJJK*^OK*RLKZRLKZ^OK +MZVN+BVMK*RKJ:FKJZNIJ:BJK*ROK"TO+"VLKJBKJ*BKJZNJK*RJKBXMKB^NJ +MZFIJ:FKJZNJJJROKBPO+RVOK*ZLJ:NHJ*BJJJROKZZNJ*NKJZFIJ:FKJ*JJK +M*ZNJJROKBXN+BXN+BXN+ZZHJ*BJJJRNKJBKJJJKJ*NIJ:FJ*:FJK:XL+BPL+ +M"VLK*RNKJZKJZNKJ*BJJJBHJJJNJJZJJJZNKJZLKZXL+"XLK*RNJZFIJ:FIJ +MZBHJJRMKZVMK*ZNJJBJJJRNJJXMKBPMK:^LK*RKJ:HJ*:BKJ*JJJJZNJJJLK +MZVOK*RLKJZJKJZJK*RNKJJHJZJJJJJLJZNHJ*BHJJBOK:VOKZ^OKJZNKJZNK +MJJNKJZLKZTL+ZXMK*RLK*BHJ*BKJZNIJ:NHJJRNKJJNKJJNKZ^MKBVLK*ZNK +MJZNK*ZNKJJHJZNHJ*JHK*ZNJ*JJKZZOJ*JJJJ^OKZ^OK:RLKJRHJJBKJBHIJ +MBBHJJJJJZ^MK2[O+RPOKZ^OJ*BLJJJJ*JBJ*J^KJJXJJJBJK*^LJ*ZMJ*VOK +MZXO+:XMKJBHJJZJJZHJ*BBJKJJHKZFJK*^NJ*FLKJZOKZZKK"PL+:XN+:ROJ +MBHIJ:HKJZBJK*XOKJZHJJZLJ*JJKJJJKJBMKB\L+:^LKJRKJ:NHJ*JJJJJJJ +MJZJJJROK:VMKZ^LK*RLK*RLKJRJJ*HHJ*RHJ*NHJJJHJ:NKJ*JNKJRN+"PMK +M*VMKZZLJBNJK*^LKJ^MK:VNK*BHJ*JHJ*FJ*BBJJJRLKZ^MK:^OKJBHJ*BHJ +M*BJJJRMK:^NK*ZLK"^NJJ^IJZNJJ*BJKZXN+:RLK*ZNJ*NHJ*BJJJ^MK:^LK +MJZKJBHIJZNJJJBMK:PO+RPN+:VNK*JJJ*BHJZFKJ*JMK:^OK*ZNJ*BIJ*BJJ +M*ZKJJVN+"\L+"^NKBZN*ZPK*JLIJJRJJ:ZLJ*^IJJBKJJBHJZVN+"^OJJNL+ +M._O+:ZIJ*JNKJNH*RHIJJBMKBRN*NDIJJVMKZRLK:TN[2PNKJBLJJJLJZNIJ +MZJJKJBHJZBHJ*^OK*RNKJZNK*^OKJZHJZJHK*ZLJZBJJJJNK*RNKJJJJJZNK +MJZNK*^OK:VMKZRLKJZNJJRNK*^MK"XMKZZN*^KHZ.LJ**NMK"TM+"PL+:VN+ +M*ZLJZBKJ*BHJJBJJ*BJJ*BKJZNIJZBJJ*^N+"\L+"XMKZRNKJBKJ*NKJZFKJ +M*JHK*ZNKJZLKJZHJJJHJZBKKJJHKJROKZ^MK:VOKJZKJZNHJJJHKZ^MKZ^LK +M*ZLJJBKJBHJ*ZBHJ*JHKZVOKZZNKJZLK*^N+B\L+:VMK*ZNKZFIJBFKJZFIJ +M*JOK:PL+*^JK*FKJZNJJJJNKJJHKZXN+BXMKZZNKJRJJJJHJZBHJ*JJJJRLK +M*RLKJZJJJBHJ*NHJ*JJJ*RNK*^OKZVMK*RNJ*NKJJJJJJZOKZ^MK*RHJJHJ* +MBHJ**JKKBPN+"XN+:^OK*^LKJNHJ*JLKZZNKJBKJ*NIJBFIJ*JJK*^MKBVMK +M:^OKZROK*RNJ*BKJ*JJJJJJJ*FKJ*JNK*ZNJJJHJZNIJ*RLK"PO+RXMK*ZNK +MJRIJ:FHJJJLKZ^MK*ZHJZFKJJBNK*ROK:^LKJZOK:PO+"^NJZHK*2DK*"NJJ +MJZLK*^LKZZNJJZJK*RLKZ^OKZ^OKB\OKZRLJZFJ*:FHJJJLK*^OK*RLKJBKJ +MZNHJJJOKZVMKZ^LK*^LKJJJJJJJKJZHJ*JJK*ROK*ZNKJZJJJROK*ZLK*RLK +MZRNKJZNKJBHJJJKJBJJJZNHJ*JHJ*JNKZXN+"\O+"XN+ZZNJJZJJ*RNKJRKJ +M:FJ*BHJ*BHIJZNJKZXL+RPMKZ^N+:^LK*BHJ*JJKZRLK*ZJK*BHJZNIJBHH* +M:NO+BXN+:VOK*ZNJJZHJ*NKJZJJJJZHJZFIJZNHJJROKBVMK:XN+:^OKJZNK +M*^LK*RNKJZHJ*BKJZNHJ*JHKZVOK*^LKJBHJ*JHK*RLK*^OKZFHJ*NKJZFIJ +MZNJK*RLK*VMKB^LKJRKJ*BHJJJMKBXN+"PL+:VLKJ^IJ:FKJ:FIJBNKJ:NKJ +MJJJK*^LKZRLKZ^MK"PO+"VNKJJJJJZJJJFJJJ@IJ:HIJZBJJJRMK"\O+B^OK +M*ZNJ*JJJJZNKJJJJ*NKJZNKJ*JJJ*JJKJZLKZ^MK:VN+:RLK*ZNJJZJKJZJJ +MJBHJJJNJ*BHJJJJKJZJKJ^KJ*ROKBXN+Z^HK"ZL*JLLJBNOKJJMKJ^JK*VIJ +MZHI*:BKJ*NOKJ^N+:ROKB^OKBVNJJRNKJJKJ:NHJJNKJ*JHJ*JJJJJNJ*ROK +M:XL+"VN+R\NK*RNJ*BKJZFIJZHIJZBJJ*JJKJZNKZ^OKZ^OK:VMKZ^OK*RNJ +MJZLJZNKJZ@J*:NKJ*JLKZVMK:VMK*ZNKJZNK*VMKBPL+:RNJ*BIJZNK*BBIJ +M:BHJJJLK*RMK:XL+:^NJJBKJJBMKBPL+BRNKJNH*"HH*"HIJZJJKJRMK:XN+ +M"VOKZRLK*RLKJZNK*RLK*ZJJ*NIJ:NKJZNKJZNJJ*TM+"TO+"TL+BVNK*NIJ +MBHIJZNJJJZJJJNIJ:NKJZBJJ*XL+R\O+RPMKZZNKJZJKJZHJZFIJBNIJ:NHJ +MJZJJJJNJJJHJ*JHKZ^N+"PN+Z^OKZFIJ"HIJZBJK*^OKZVMKZRLKJZHJZNJJ +M*^OK*RNKJRLK*RNKJRLKZRLKJZKJ:HKJ*JJK*ZNJJJJJJJJJJZJJJZNKZ^MK +M:VMK*^NKJJJJZFJJ*@HJZBJJJRNKJ^OK*ROKJZLKJZNK*^MKZ^LKJJNJ*NIJ +MZNKJ*BJJ*JJK*RNJJJNKJRNKJRN+:^OKBPL+BXOK*ZLJ:HH*R@H*BNJJJZLK +MJ^JJZRMK:VL+"XMK*^LKJZNKJBIJ*BHJ*NIJ:NIJ:FIJ*JLKZ^N+"PO+2POK +MJRLKJZKJ:NHJJBNKJZJKJZHJZFJ*BNHJJJOK"PL+RXL+ZZJJ*ZKJJBJJJRLK +MJZHJZFJ*:BJJJJHJ*BJJ*VN+R\O+"PN+*ZHJZNKJ*NHJ*BHJ*NHJJJLK*^LK +M*ROK:VMKZRNKJBMK:^OKJZNJ*NIJBHKJ*FI*"FIJJBOK:VN+BXMKZ^LK*RNJ +M*BOK:XOKZRNJJJNJZFIJB@IJZNHJJJHKZ^OKZ^NK*^LKJZNKJZNKJRLK*RLK +MJBHJZFHJJJJJJZJKZ^LKZPOK*VLK*^LKZ^LKJZHJ*BHJZFIJZBKJZBJJJJJK +MJJNJJRLKZ^OKZVMKZVOKJZNKJBKJZNKJ*JJJJ^OK:VLKJZJJJJLK*ROKZ^OK +M:^LK*RNKBFKJBNJJJROK*ZNJJZNJJBKJ*BHJ*BJJJZOK:VMK:VMKZRNJJBKJ +M*BIJBHKJ*JLK*^MKZRNJ*NHJ*JJJ*JJK*^MKBXN+:^OKJRNK*JJK*JLKJNJJ +M*BHJ*BJK*RLK*^NKJJNKJZNJJJNJJROK:VN+:ZLJZFJ*:FKJ*JNKZ^MKBVOK +MJZJJJBHJJJLK*ROKJRKJZBKJZBJJJJJKJZLK*RLKJBKKBXN+:RNJJJHKZRLK +M*ZNK*ZHJJBHJZNJ*"HIJ*JJK*^N+"PO+RXLKJRIJ:FHJJZLJJZJJJJKJZNJ* +MZJLKZVOKJZJKJZOKBXL+2\L+:ZJKZ^IJB@J*:NJJJBNK*^OK*ZNKJZNJ*BKJ +M*JHKZ^LK*ZNJJRLKZRNKJZNK*NKJZJHKZRLK*RLK*ZNKJZHJJJJK*VMKZ^LK +M*ZNK*RNK*ROKZZOJJZKJ*NJ*:NKJ*BJKJZJKJZNK*^OK:XMK:VN+ZRLK*BKJ +M:HIJ*BJJ*RLK*ROKZ^LKJZLKJJJJJJJJJBNK*ZNKJZJJZBHJ*BKJZNHJJROK +MR_L+RPMK*ZHJZNIJ:NKKKV<"!I.^_A..2A.BZW-K6X,+8R.J>YNZNTO"(XJ: +M.XLO&UY'6[C?VM:'#J['3AL?6H^CB@.G$V;C*X9STN[O6@_GHWXK(L:#COLO +M#H\KPU."4RH#2K(;>@MG#J:)-N9W:%]#%I>F6X?V9\HJ\\[O,Y*7HRZ#7MO^ +MM@]./N^NCPLC;Y+GOW[?P^J[VFM:@ONNDA,2(B_.#U):W^:_:J)/^J/:,VKC +M2U\OEL>H'H]VOTJ>]^XSYPY?[TO;(DJ[)L,N^NHZ*CJC^NK[N[/"BX^NC\H" +M3R(#>HMK0P(ZJAH[GB/B@J^^#]O[JVM3RGHK[MM[_I\NK[,^+P,Z6ZI"HZ.. +M@\N[NGXOJK*O[F-S[KM*NZ):NNH;FWLZDR]NK\-:.KK+4LOS7O__/B^"Y^:. +M1RCSOZ8/XY/Z[D=RYE>F3F<FRSZ_"U:'8KX##ZM*9V)NYTIR[QMZKJ,O-N]S +MIF<JXF^*XZK2I[Z+JW(*RIH.,PJCXHL[TN\:HLM34HJ/+L^Z6BK+ZWMN#[MN +M!TY#_W+:R^JZ#N^COH?ZCG^+RN:GH^;3KMMR>AK>HX]NB[]KVM^KBD\NPZ:# +M`Q;W,J:'[IL/FW_B*F-^>VO^+TIN)VZ3K[8G[G(*_H?*DI]J0Z-N:R^2`DL+ +M2X+B&[I*R]ZGXVY/N@^BGJ>.0T,^[X\:VVIK(PY*$HX/#MX/B[H+^[OZ:V-J +M6T^K^C,C>\X3RHYSVOOB:N_*2\J*TR[B^[*+PF*_6IM;"GMZ*HHN2\N.LROZ +M"]M3^Z-/@GNSPFK*&W*.JNMJ2LO;.TM*N[-*BZI+FC**@H*J[FI;,ENJ\W-+ +MK\-O.^HC6PJR>H+*PAJZ^LOBFYM+:QH[N^O+:NH[@VIJ`VNK:BHK@J[BCF[J +M$KHZ:Z,"0^."ZI-+N[./SZJ?$Z\?N^]["VM:B\K2`@H*ZEO3KQ,_KXO[>DZF +MQK:H*%8HJ/:&GG*#;__W=Y<7U]?GAZ=3\ZJ;;R.*TW.CNVNJ[PGYLR_9B4L. +M^NOH>!C@H.#`@!@(".AJA\<I.:%AX2%9V=FI+P,JADBX:$@XR%:FKCKSQRDW +M9U?7Y],O[SH^)M[.TMI7F5^G(7FW#[_GM@A((*#@P(#@2,@(^J<WR7DA(2'9 +M">F7:J8&=NA(:%;V)DX;QY<7Z0D)J3<WIXM./B/IN;H2H;DKYD[_J*#88*#@ +MP("@*-9H`O=I23GAP6&AN;F)R\:VMNA8&.C65E:.)T?G!XDYUV=W%^=NLI=9 +MH>MS01FC)@Y':(!@0&!`D+"`"&CXSJFY27G!,0'AH=G)_VZV%FB@(#CH:(@F +M+Q\G%XD)Z=<WMV?;GG+G&2&N+_&A;]Z+:8A@H,#@0!`PP$B(6!Y724FYP?$! +M8:%9^0\^-JAH(.`X:.@(QD^G9W<I20E75[?G;^+#R0&)QEE!%WXH9P(`8$#` +M@'"P0%BF:*C_N5G)H?%!@2&9^7=:]F@H.."@R%9H:#(?9P>W"<FI-\<7_VYJ +M!QD!7XI!84?F1JF6P&"P@$`0L+#X!L@&Y_FAR>%QL8%9F?EGCJ@(*)C@H,BV +MZ.B*1Q?'5WE)J7>'A]M.KMIIP;=&8;$)SE;)JX#@0&``$,#PX`9HJ#K)84D9 +M,3$!6?EY!_JV2.BXH"!XQK;HCB<I%[<)28GI)T\?>X[F/V%9QL>Q6<_H\]=X +MX&#`8/!`P+!H!E:FGR&A26%!P8$9^:E/2NA("#B8H$@&ED;:WQ=WJ>G7*=?_ +M\Z/J>B=A8>*WL>&'Z/K7^(``0`!PL,#P.&8&7O.A@=F!,;$!6?E7NQ*HF!@8 +MF*!X=H;>JN?IZ6D)Z6F7OV,+"KY+H8%#KX&!Z?9^5]8@@$"`\+``\""6IIZR +M28$AX<&Q02&9*8^+AC@8F#C86&C&WO(S-REIB2FI5[>_:LY.R[EAI\HA`?F^ +M1JD:F&!`8$`P`/"`:&8^IL?AX:'A`4%A&8G?0Q+H>%@X2!BX5A[Z*W^7Z0DI +M%ZE7!PNN8AK_V=F;1^'AJ9:R!Q98``!@,,``L""H+M(":6%AX6'!P2'Y=\N" +MYHC8H+C(.,@6TD./!ZEIB2E7=\<G@V).>DEA!\JYX=FBUA.^""!``$``X$#` +M^![C4L\9@0&!@<&!H4DOKLXV2."@N$A(B+8*C\>7J8D):=?G)Q_C+J8"*2$I +MR^E9H2<V(DZH^`#`0,"@`,`@%K.[(VFA`<&!@>$AV<<")L96&*"8.&@H%M[* +MAZD7%RD):4??CT/CXK[K25GG?^EYN1J^;M;H&.#`,.#8X(#8GL_O1PFA`<&! +M(9D92=^.]A;H.)@8.*BV)LY;]RDIJ=<IJ0?_(S,#;IZ?V;G3AVEY5VZ21FB( +M&.`P,*`8(."X<C]G*;FA@<$!63FY*<_>J&C(N/B8N"AF4DK/MZGI*:G7M[?G +M;WNR#LXG&6FOYREY=]*N-JAHF""PL*`86"`XCH]'Z4G98<'!H;D)J5^NEFBX +MN$@X.,@V`KO/9Y=I:>E7QP<'7P-2/O[:*4E?KR=I26_BWE:6B#C@L&`8>!@8 +MJ,)/J<DYV>$!@1D)%V=33I9(>+C(R,AHAN+OA\>7Z0D)J;='AY\;KOYFGL<) +M9\-/5XF?"V[6J&B(&`"`H/A(2*A>R]>Y>7D9X6%9R?=/>U+FZ#CX2(CHJ`8N +M<\<7J2DIZ2FI]U\SZQJNY@:KU[?O;Y]WA\^SYE;HZ(B@8"#8N,BH!LZ/Z?D9 +MF=FA67F)QY,BSH8H2#BXB%;&IA*OQU<I*:FIJ=?'OPORCKZF!IY?5P?GI[?W +M7]_*1BAHZ+B@(*"82.A&IF+GB?F9F=G9F3DI)RONWO;H2#A(Z/:F;JK/QU?I +MB>G7%Y?'#[H.)F9FQAX_ET>'9_?W)U_K9JB(:#B@(*`8.&@&ONIGZ;EYV:'9 +M>4DI9Z-2YM9H"`B(:!8FLD-?QY<IB6FIE\<_&Z+.YD:VMK;.ARF7][>I5T?' +M8^8HB&@XH*`@H'AH!I["3]>Y&:&A&7DYB7?O\H96*&C(R`BHAA)#GX=W*8F) +MZ1=GST-K,B9&MD;&AK('5Y>7=ZEW!V<K9BB("/C86*#8^"AFSBO?UTF9H:$9 +M^4GI-P^B9E;H:(B(:%9&OIL?QW?7*>DI5T<?XSJ2?F;&1K9&AA*'*:E7=Q=W +M1[>OOM8(R/@8V*"@V`C&;GNGEPF9(>&A&;GI-[]*)J@(2$B(*!9&/ILG%^EI +MZ2FI5T=/BLYF1O9V=O8V1EXOZ<G)B2DIEQ>W2X:(^)B@H*`@(-AH9@I?=VDY +MH6%AX=G)5Z<CKK9HN'@XR"CV9NZCYU=I"0EIJ3<G+\K^MJCHZ-9&YAY.F@>Y +M&1GY":G'QQ^"=CB@X&`@(*"@F&BFDY<)^=DA86%AH4EW+Y)FUFBX>)@X:$;. +MZR\G]^D)R0FI)V.:TG[&%BCHJ,:^>GNSG^EY&5GYB4?3(X)FZ)@@@(#@6/C( +MZ`9"IVEYH:&AH5G9^>GG^H96Z&B("`AH5F8BCV?W%U<I*5?'OTLN)K9VEA;V +M1N9.>J^G!ZFY>7DY:7>O.HY&*+@8(.`@&+CH=E["+_=I.9D9&?DYR>DW#R+F +MEJ@HZ.@HJ#8F@L.?![<W-S='YT^CPAZ&QL:&9J:^8GOOGU]?-XG)28D7WPH2 +MOF;VZ+C8H-CXB-;&'BZ[I]>)N?DY2<F)*7??R[Y&EM86EI9V-F8.JH^G9V?G +M9V<G3Z-Z4OXF!L9FWFX:"P,O_U\G-^F)B>EWI\O"SF8V*`CX&'@X"*A&GI([ +MGS<I"4FYR0GIU[=?X_*FQG:6=C;&9AXN^J./IX>'9R>?+TNB+DZ>9D9&9L[: +MVR\_7Z<G9Y?IB6FI!_-R?F:VEB@(.)AXN.@VWI**<Z<W*<DY.<F)5\?_X]J^ +M9C9V]@9>;J*+6Y./OS_/+Z-*$KX>7MY^/H[RNB./7^?GYU\_7S>I*=?'#X*F +M!C:65B@(N$@(J(:N2U-/'Z>'-]>IUS?G#V-K"MI:6N(BVKH+H\,#V\N*HK*2 +M4NYN#K[^OFXR.KL#4X\_GY]_/Q_'%]=WMZ<[+EY&=A;6*&AHZ*C&3GJC;[^_ +MGR>'Q\>'I\]S&VNJ"WO[N\L+"SL;&WN[*YJRTNZ.C@Y.OD[N0DH+XQ,O;V^/ +MCP]_)X>'9R=/H[JN_J;F!C;V=O9&YC[2>@NC0U//GZ<GIW_/$R,;V]L;V_MK +M*ZJJ*PN+Z^IZ`G+2$JXNTM*20F)*RX.3+Z_OIW=7U]=W_VH27L;&!C86%E96 +MMJ92BR]/+U.3TR_OC^^3XPNJ:X//'Z=??T_38Z,[JAIROJ8F)J:^K@):FMJB +M2FL;,Z_3<[,CV^.SD].O+Z^OTW-#HTMJ(E+._GZ>GIY^_DYNDMKJ2UO#,T-# +M0T/SDY.S(QN[:RLKB_O;6]O;>\O+NSM[>[LKBOJB8F)ZFR_O+R]C>D)R[BX2 +M4@X^?AX^+B(K8Q.30X-CP[.S0R.[JLKZ2HNC0Y-3T_.SL\/#PZ,KVD*N[BZN +M4G*RDI+"HKJKRSL[.POKZPL[VUN;>_M[&V,SDZ\3X_N+JVJ*2OI:@D)"XIJZ +M:NH*NGK:VIIZ^CJZN@KJ*\M[6Z,CH]N;NTL+:ZH*.IJ:.HHKN]MC8V/C(R/C +M(YN[ZPJ:VIK*ZTM[VTMJFJ+B@B*:&N*R$M(R`IIJ:XN+:^L+^R.STU/S8YM+ +MNWN;FQN;2^LJ:BJJJZNJ:DKZFMK:&IJ:>OKZ.CHZ2NHKB\M+2SL[NTN[.SL[ +M.[M+R\L+"PO+:VK*NOI*:BMKBPMK*@I*RFJKJRH*^MK:&GK**BN+"VMKBXO+ +MNSL[2XLKJJLKB\L[>_O[.XOKZVOKJNJ*RKHZ^KI*RLJ**NKJJJLJJZNK*ZJJ +M:^LK*ZNK*XO+R\O+"PL+B^LK*RNK*HK*2DJ*JVN+"PMKJZKJBFKJZNIJBHKJ +M*JIK"TM+"XLKZLJZ.IH:^DJ**[N;6^-C8^-;F_O+:RMJBLJZRLH*:NKJ*NKJ +MJFH*:HJZ.CJZ2HKJ*BN+"TM+N[L[.SO[2PN+ZZNJJZKJ:HJ*:HJ*:FHJJRNK +MJRLKJBJJJRNJJZKJZFKJZBJK*^OK:^NJJFLKZVMKBXN+"VOKJZNK*JJJJBOK +M*ZNKJNHJZNIJZFJ*ZJJK*ROKZROKZ^OK:^NKJBHJ*BHJ*JHK:XN+:ZLJ:FKJ +MZNKJ*JJKJJHKZXN+*XN+JBLKJZNJZJJJJZLK*RMKBRLKJBJJJBIJBHJ*:BJK +M*^MK"POKZ^LK*ZLJ:HIJBNJJJ^OKZRLK*ZNJJZNJ*JJJJZOK:XN+:VMKZRNJ +M:HH*NDKJ:NHKJZMK:XOK*RLK*ZHJJJOK"TM+2TO+:RLJBLJZ.DH*"HIJ*BHK +MZVN+"XL+B^NJ*JJJJJNJ*^OK*RLK*ZNJZFIJBHIJ:FIJBNHJJNM+N\O+B^OK +MZRLKJZJK*RLKJZNJ*JLJZNHJ*NHJJJJKJJNKJRLKJZJJ*^LKZ^LK*RLKJZLK +M:VOKZ^NKJNIJZFIJBFKJBNHJJBLK:^LK:VN+:RHJ*ZJKJJHJ*JJK*RMK:RNK +MJFJ*R@IJ:NHJ*VN+"PO+2\N+:RNKJZJKJJLJ*NHJ*BJJJZNJ*NIJZFIJ*BHJ +MJBMKBVN+:XL+BVLKJZJJJBHJZZLJ*ZJJJJHJ*JHJZNKJZNJJJJJJ*ROK:VN+ +MBPO+"XOKZ^OK*RNKJRKJ:FIJ:NKJ:FKJ:NHJJJOKBPL+"XN+ZZLJ*NIJZNJJ +MJJLK*RLK*ZIJ*JNJJBLK*RNK*RLKZ^OK:VOKJZNJ*BKJ:@H*:FIJZJHK:VMK +M:^N+BXMK:^OKZRLK*RLKJBHJB@J*:FIJ*BHJJJNKJRLKZVOKZVMK:XOKZTN+ +M*^LKJZKJ:FKJZNHJJJNJ*BKJZJJJJJLK*RMK:RLKZRNKJJNK*^NKJJHJ*JJJ +M*NHJJZNKJJJJ*ROK*RNK*JJK*^OK:VMK:^OKJRJJJJNJ:BJKJJLJZJHJJZJJ +MJJJJJJNK*BHJ*BJJ*VN+BPN+ZZLJZHH*:FIJZBJKJBJJJZNK*RLKJZOKZ^LK +MJRLK*VN+:RNKJZKJ:BKJ:HJ*:HKJ*JL+BXO+"VMK:XMKJRIJ:NKJJJHKZ^OK +M:^LKJZNK*NIJ:NKJ*BHJZBJKZRNK*RLKZ^LKJZNJJZNJJRNKJZNJJRNK*RNK +MJJNJ*NKJZBJJJBMKJFJJJRJJJZMKBVOKZXN+:^OK*ZNJ*NJ*BHIJJJLK*ROK +MZ^OKJROKJRKJZNHJ*JLK*RNKJZKJ*BHJ:FHJ*NJJJZNKZXL+"XN+BVOK*ZNJ +M*FHJ:ZKJJRIJ*JNJJBMKJZJJJZLKJRLK*ZKK*^MKZ^MK:RNKJBHJ*BKJJJLJ +M*JNKJ^LK*BJJ*JHKJFJJJRHJ*VN+:ROKZZNK*ZNJJNKJJJOJJJMJJJKJZJKJ +MJNLK*^N+*RL+BVLKJRNK*JJKJBJKJFKJZFH**JHJJZJK*ROK:VNK:\N+:VMK +MZRLJ*NLK*FKJ*BHJZJMKJZJJZHHJ*HKJ*BKKR\LKJNLK*ZLK"^NJJJNJ*^NK +MJZNJJBIJBFHJ*^NKJXL+BVN+:RNKJBJ*BFHJ*JJJJZNKJBOKZPN+ZRNKJBHJ +MZBHKZZLJZBJKJRLKJZLK:RMJ:JJKJJJJJZHJ:LKJJRJK:^LKBXOKZVMK"VNK +MJZLJ*BLJ*JNKJZOJ:BHJ2LHJZBJJJNL+*^L+:^N+Z^MK*^N+:RLKJBHJ*FHJ +M*FIJZBJJJJKK*^MK*RNK*NKJJBIJ*BOKJZLKBVLK:^LJ:NHJ*BHJJJKJZNMK +M*ZMKBVOKZVMK:^MKZZHJ*JN*N@HJ*FKJJZNJJ^IJZ[O+BVOK*ZNKB[L+*^KJ +MBFH*NNIKZRMKBPMKJBHKZZIJB@HJJHIJJBLK*ZNK*^OK*ZHJJBLK*VJ**HOK +MJ^N+R\N+BXOKJRIJ:FIJBFKJ:NJK"XMKZZJ*"NKJZBIKRVOK*^M+2PN+"\OK +M:DI*2@H*2LH*BFJKZ\N[2PN+RTL+Z^LKZFH*RHJJJFIJ*POKZJH+2TM+JHHJ +MBCHZR@KJZ@KJBTL[>_N[N\NKJJLJ*@K**\O+BRLJ*JKJBJHKZLJZ.@JKZ^OK +MJZOKJNJKR\N+:RNJJZKJ*JOK:VN+"\OKJFK*RFJK*NJJJZLJ:HJJZZNKZ^LK +MJFIJJBOKBXMKZ^N+2TMKBRMJ.KKJJRNKZHHJ*RN+:ZLKZVI*NDKJZRNJ*\L[ +MFWO[.[N+*XK*"LI*RLI*RHKJJBMK"XLJ:JMK"\L+ZRLJRLKJJNMK*^MK:PMK +MZXOK*BJ*:JKKJRKJJRJ*:JIK"\OK*NIJ*BOKZXLK:DKZ.LJK*ZN+"\M+RTL[ +M^TN+JXI*BLI*RLIJZBJJJZLK*VN+B^OKB^OJZJNKJZJJJBLK*VLK*JNJZFKJ +MZFIJJ^MK*^LKZ^LK:PN+ZRMJBBKJ*JJJZVNJ*JLK:PMKJRNKZHI*RNJK*JJJ +M*XMK:VMKZZJJZBIJBFJJJBMK:^LKZZOJZJJJ*BKJJJJJJZJJJRLK:XO+RPN+ +MZZNK*NJK*RKJJZKJZBKJZJNJJZKJ:BJK*XMK:PMKZRLKJBKJZBKJZBJJ*BHK +MZRLKJRKJJJNJZVMK:XL+:VN+ZRNJJJJJJBJJ*BHJJJHJ*NJ*ZBHJ*BJJZVOK +MZXMKZ^LKJ^LKJJNJJRLKJJJJ*BJJJBOKZVN+JRHJJZNJZXMK:^OKJZLJZBKJ +MZNIJ:HIJ:FHK:PL+:VOKBPN+*RNKZBJKJJNJ*BKJBHIJB@KJZNJJ*ROK*RN+ +MRTO+2TL+"PMKZRNJBHJ*2DH*:BHJJJJJJJOKZRNKJJHJZBJJJROK:VMKB^NK +MJZNJJJNJJJNKJJOK*ZNJZNIJZNKJ*BJJ*RLKZVOKZ^NKJZNJJBNK*JLK*^OK +M*^LKJZKJBHKJ:NIJ:NKJJBMK:XO+R\O+"^LK*^OKJ^H**JOJ:NKJJBNK*^MK +MBVMKJRKJ:FIJ:NHJ*BJJ*RNKJ^LKJBHJJJNK*^MK"TN[NTN+*ZNJZFIJZBJJ +MJJNK*RNKJNIJBHK*2DJZ2FHJJNMKB_N[RSL[R\L+RXMKZ^LKZ^LK*ZNJZHJ* +MRHIJBFKJJJHJZFJ*:BHJJBOK:VMKBXL+"PN+:VMK*ZNJJZHJZNKJ:FKJ:FIJ +MZNJJJRLKZ^MK"PMKJNOK*JHJ*BJJJRLKZ^LKJZNK*BHJZFJ*ZJHKBVMK:VN+ +MBPMK:RLJZFIJ"@H*NKHZ2LIJJ^MK:VL+2SO[>_L[2XLK*NJ*RDI*2DJZ"FJK +MZPL[2PO+:^OK*RNKJRJ*:@K*"HIJJJHK:PO+2\O+"XOK*ZLJZHJ*"HIJZBJK +M*^OKZRLK*RLKJZLJ*JJKJZJKJJJJJZNJJZNJ*RNK*^OK*RLKJNJK*RMKZZNK +M*ZNK*RMKBPMKZZHJZFIJ:NKJZBHJZBHJJJOKZVOK*RMK:^LK:XMK:RNJJJNJ +M*BKJ*JJJZBKJ:NHJZNHJJRNKJZNJJJLKZ^N+N\L+RVLK*ZHJ:FHJ*JJK*ZLK +M*RHJZNKJJJJJJZNKZXMKZ^OKJZNJZBKJ:BJJ*^MK:VMKZRNJZBHJJJJJ*BKJ +MZNKJJJOK:VN+:^LKJJNJJNH*:NJ*JJNKZVN+BXN+*ZHJZJJK*ROK*RLK*ZOK +MZ^LKJZKJZFJ*"@J*:NHJJJJJJBOKBPO+RXN+:ZLKZRLK*^MKBVLKJFH*2DJZ +M2LH*:FIJ*\L+B\N+:VMK:XMK:VOKZ^OK*RNKJBHJZFJ*"@H*"HHJJBOK:PN+ +MBVOK:^MKBXMKZRNKJZHJ*JJJJBHJ*NKJ*BHJ*BHJJJJK*^MK:^LKZ^NJZJNJ +M:BHJ*BHJJJJK*RLK*ZJJ*ZNK*RNKJZNK*^OK*^LKJRLKZVN+:^NKZFKJZBHJ +MJZLKJZHJ:HIJ:FKJJBLKZVMK:VMK*^OKZRLK*ZNKJ^L+*ZNK*BHJ:HJ*BFKJ +M*BKJ:NJJ*^OK:XN+:VN+BXMK:RLKJVH*"@J*:JHK*NJKZRMKRVLK*BKK*BJK +MZ^LK:ZJJZ^OK*ZNJ*BHJZHKJJJNK*BJ+BVMK*ZOK*ZJKJZNK*ZJJJZLK*ZHJ +MZNIJ:NIJ"FKJZJHKZ^OKZ^MK:XMKZ^OKZRLK*^OK*ZNJ*BIJ:FKJJBHJ*BHJ +M*BJJJROK:^OKZVO+^\M+2VOK*^J*"@H*R@IJ:FIJ*BKJZJHKZVN+"PL+RTN+ +MBPMK*ZNJZHJ*:NKJ:FHJ*BHJZNKJ*JLKZ^OKZVMK:VN+BVNK*JNJ*JJJJBJK +MJFJ**BIJ*JJK*^LKJZHJJBLKZVMKZVOK:^OK*ZJJJBHJ*JHJZBHJ*NIJ:FKJ +MJJLK:VLK*VMKBXN+:VMK*ZNKJBHJJBHJZNKJ*NIJ:NKJZNIJ*\MKBPL+"PL+ +MBVOKJZJKJZJKJ^KJ:NIJZFIJ*JNJJJJKJJNKZVMKBVMKZRLK*RNJJBKJ*NIJ +M:BJJJJNK*RNKJJHJ*BJJJJNK*RMK:XMK"VLJBBKJBFIJ*BLKZVMK:VOKZRNK +M*ZLKJZHJ*NIJ:NKJJJLK*ZJJJJJJJRMK*RLKJRLK*^OK*RNK*BJJJZJJJBKJ +M*JNK*^OK:VOKZRNJJJLJZBMKJZJJ*JKJBNKJJJJK*RMK:VMK:XMKBPN+:VLK +MJZJJ*BHJB@H*BHIJ*JJKJZNJJJJK*^OKZVMK:XL+BXOK:RNJJBIJ"@IJBFKJ +M*JJJJJJJ:FJKJJOKZVL+"PL+BVLKJZHJZJJK*^LK*ZNJ*BIJBFKJ*BIJZBJK +M*VN+:XMKZZNKJJLKZZLK*RLK*ZNKJJJJJJHJZNKJ*JLK*^MK:RLK*ZOK:ZNK +M*ZLJ:FIJZBHJJZNKJBKJZJJK*^MKBPN+"XN+BVOKJZNKJZHJJJHJZFIJ"@J* +M:NHJJJLKZVOKZXL+"XMK:VMK"XOKJZKJ:HJ*:JJKJHH**FKJJZOKZVOK*ZNJ +MJZNKJZJKJJJKJZLKZRLK*ZLJZNHJ*BHJZBJK*VMK:VOK:^OK:VLK*BKJ:BJJ +MJZNKJZNKJZNKJZNK*RLKJZHJ*NHJZ^NJZRNK*BHJ*NJKJJOKZVMKZ^OKZRNK +M*FIJ:NHJJJNKJBJJ*ROK:^MK:^MK:VLK*ZKJ:NJJJZLJ:NHJZFIJ:FJ*"FHJ +M:PL+"\N[2\O+"^LJJBNJJZLJJJLJ*NKJZFKJZNJJ*^MKZRLK*ZNK*RLKJNJ* +M:NHJZHKJJZKJZBL+"PN[NPO+RXNJZFHJ*@IJZJNJJNNKJFHJ*NHJBJHJJFL+ +M^_M+*^NJRNI;VTZNS_.&B+JI6RHWWVLGNB@&/[EI%GBVZ>F^Z,:G?VL^4R<> +M:!8'*6DW1H9JJH;6'LIWJ6=_RCH/[\[.2NH"4N*:`@8>^Z^/3]_;;MY:<[O* +M[@-GAS]#[WL[;H:6)BMZ$D(#_R=J+A-:HY_3"PXJ:TN:>J.#^SX>PT^3:^8^ +MRLL_PY.J(AL"8QH*;T/CDOI++JJKTEHR>VO[4V._XTMJ2ANZ@LX.D@K;NNI[ +M`X.;VVNK2ZOJ#@XKS[.#"HK/`WMRJ@M"HC*R\HJZ2P]O;R,Z#H)+VB+Z"^H[ +MJG*KKV^S:RZJ6\K";G,;:\IBLTOC"PMS>IMZ+NZR\^L+&TI[Z\L[ZVM:*H/; +MNV+Z2KJ#2\NKXLKKVZHBNHJ+:_KR:W.#^JJC2]MKDD*K8R,KVF*Z8ULKB^KC +MZT+RDOK::CN;LQL;8V-CZX*B2_MZRJ)BFV/+J[OJ^GH*HVM:@FK+R^NK0^-; +M*H(K2ZM:`AJK$UO:`HHS,PNZTIJ+ZKOK"FLK&PNJRSL#ZWJ:"JLZF@KKHXL* +MJ@I*BNKK.AL[2@M+XSLJ2MHJ*@IKJNMK2RJ*NJLK*WOJRXNKB^MJ&OHKBQOK +M.JKJ"HJ+*VL+(TLZVDK;:[KBNOMC@^LJZFL*2HLJ*WIJRFM+"FM+.VOK.RN* +M^H):"IM;.TNK"_OKJFH:&KJ*"LL[RWNKZ\N[*[H*"LIZ2FK**KL;VXN+>RNZ +MHMKJ"[N+ZWL[NXLKZDJZ.@JZ:NNZ:@O+*^L+.QNK>NKKJTH*JXO;"XK+NRL* +M2KKJ*DHZ*@NJ:KK*JKM;RXO+NRMJBPL+*[JJ*BNKJRN"#J["&FIK.QLCXV/C +MXZ-;&WL[NPN+ZRNJ*NIJB@H*"LK*R@K*"@H*"HIJZNHJ*JJJJZLK*RLKZ^OK +MZ^OKZROK*RLK*RLK*RLK*ZLKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNK________________________________________________________ +#____ +` +end diff --git a/share/isdn/3.g711a.uu b/share/isdn/3.g711a.uu new file mode 100644 index 0000000..de5aa8a --- /dev/null +++ b/share/isdn/3.g711a.uu @@ -0,0 +1,322 @@ +begin 644 3.g711a +MJZNKJBKK:RJJJNKJ:NKJ*BHJ*JJK*^N+:VN+:VOK*ZNJ*NKJZNKJJJJKJ^OK +MZ^OKZRNK*JHJ*BJJ*BJJ*^OK:VN+B^LK*ZNJJBKJ:FIJ:NHJJNL+R^LK:ZNJ +M*NHJ*NJJJVL+NTO+:RLJ:HJ*:@J*BNHJ*JJJ*NKJZJHK*ZOKBPL+BVMK:^MK +MZRLK*ZLJZBHJJJOK*RNK*NIJBHKJZBJJJZLKZ^MKRPLKZZLJ*JHKZVN+B^LK +MJRHJZFJ*"HKJJJHK*RLKZXN+:^LKJRJ*BFHJJJLK:VMK:^LKJNIJBHJ*:NJJ +M:\M+2TO+B^MKZ^OKZZHJBDI*RHH*ZNLK*^LKJZJJJROK*RNKJZHK:XO+RXN+ +MZRNKJZKJZFKJ*NKJJBHJZBHJ*JJJJJNJJJLK*RLK*ZLKZRLK*^MKBXMKZRNJ +MJBKJ:FIJ*JOK:PMK*BKJBFIJ:FHJJROK:XO+2\N+ZZJJJJHJZBHJ*JJK*^LK +MJZNJZFJ*ZNHJJ^MK:VMKZ^LKJRHJ*BKJ:HIJZNJJJZLK*XL+"\N+BVNKJZNK +MZJKK*RNKJZHJ:FJ*BNJKJ^OKZRNKJNJ*"HHJ*VO+N[M+"^NJ*NKJ:BHJ*BHJ +M*JKKBVLKJZHJ*BHJZNIJ:FKJJNN+R\O+"^NKJBKJBNHJ*NO+"ROK*ZHJ:HJ* +MBBJJJROK:VMKZRNK*BHJ*JHJJJLKJZJJ*BJKZ^MKZ^OKZRNKJJHJ*BJJJROK +M*^OKZ^OKJZHJJBKJ*NIJ:BHJ*JJKJRLK*ZHK*RHJ*JNKZVMKBPN+B^OKZRNJ +MJJJJJJKJZNKJZFJ*:BJK*^N+:^OKZ^OKZ^OKZ^N+:^OK*RLKJZKJB@J*BFHJ +M*BJJJJHJZBJJ*^N+"VN+2VNKJZJKJJNKJZLJ*BHJZFKJ*NKJ*BJJJBJK*XO+ +MNSO+"XOKJZHJ:@H*R@IJ:JLKZ^NKJBJJJBJJJ^MK"\O+RPN+ZVOKJRKJZFK* +MR@J*ZNIJJRLKZVLKJZNJ*JJKJZNJJBLK*^LK*ROK*ZNK*ZHJJBKJ:HIJ*JJK +MZ^OK:VLKJZHJZJHK*VN+BXL+B^LKJBJJ*NKJZBHJ*JJJJZNJJJJJ*XLK*^NK +MJZNJ*BKJZBJJZ^MKBRNJ*NHJJBNKJBHJ*JNK*^LK*RLKJZJKJRLK*RLK*RLK +M*RNKJBHJ*BKJZNHJJJLK*ZOK:PO+RXMKZRLK*RLJ:BHJZJJJJBOKJRKJ"DI* +MRHJ*:BJJ*VN+R\O+"\L+:^NKJZLJJJJKJRNKJNJJJJOKZZLJBHH*:NKJ*JOK +MBVLK*RNK*^MKZ^OKJZNKJZNKJBMKJNJJJJNKJZNJ*JNJJBHJJJNK*^MK:^LK +MJZHJZNKJ*BJJJZLK*ZNKJZLK*ZNK*BKJZBJJJ^OKZ^OK:VMK:XMK:RNKJBKJ +MZNHJ*JJKJZJKZFHJJBJJJJJK*XL+"PN+ZZHJ*BHJ*BHJ*BHJZNJJ*NIJ:BJK +MJRMKBPN+:RLK*ZJJJROK*ROK*ROKZ^NJZHJ*BFKJ:NJJ*ROK:VMK:VOK*ZMK +MBRNKZZNJJJHJJJJJ*JJJJBJJJBKJ*JJKJRLKBPO+"XLKJBKJ:FKJ*JLK*ZNK +M*JJKJZHJ*JJKJZNKJZNKJZNK*^MK"PN+:RLK*ZNJZFHJJHJ*JJJJJBHJ*JHJ +MJBOK:VOKZ^OK:XL+"PMK*ZLJ:HJ*BHIJZFKJ*BJK*RMKZ^LK*NKJZBJKJBOK +MZXL+"PN+B^NK*FJ*ZNIJZBJJJJJJ*^LKZ^OJ*JLK*RLK*ZNKJJHJJRMKBVLK +MJZJJJJHJZNIJ:NHJJ^OKZRLKJBKJJJLK:VL+RXMKZZLJZJJKJZHJ*BKJ*JKJ +MZNHJJJHKZVMK:PL+"^OJ:JHJ*JHJ*BJK*VMK:^LKZFJ*BHKJJRLK:^OK*ZNK +M*BKJZJJJ*ROK*^LKZ^MK*^MK:^NK*HH*BHIJZBJKJROK*^OKZ^LK*^OKZZJJ +M*RLK*XN+JJJJJJNJJNIJZNKJZNKJ*JJKJ^OK*RNKZXN+BVN+"VOKJZHJZNIJ +MZNKJZJJJJJHJZNKJJJOK:XN+"\L+:^LKJRKJZNHJJBHJ*NJ*BNHJ:NKKJROK +MZ^MKZROKBXO+2\L+ZZKJ:FJ*:FKJZNHJ*JJKJZHJZFKJJJN+RTO+B^LKJZNK +MJJNJJJJK*RNJ:FKJ:NHJZBHJ*JJK*VN+R\M+:RMKZRJJJBKJZFIJZJOKBPL+ +M:ZLJZHJ*ZBHJZNJJJZLKBXO+"XMK*ZIJZJNJJZNKJBJJJJHJ*BKJ*NKJJJLK +MZXL+"\O+B^NK*BKJ*JLK:XL+BRHJJHJ*:FKJ*BJJ*BHJJJNJJRLK:XL+"PL+ +MB^NKJBHJ:@J*BFJJJRLKJZNKJJNKZ^LKJZJKJRJKJ^MK:XL+B^LKJRKJ:HH* +MBHJ*:BJKZ^OK"XOKZ^LKZ^LKJZNK*RLKJZLKZRNKJBKJ:FIJ:FIJ*JJKJZNJ +MJROKJZLKJRHJJBOK:XMK*^OKZ^OKZRNJJNHJ*BJJ*FKJ*NKJ*BJJ*ZLK:^LJ +MJBLKZXMKZ^LKZXN+:VLK*FH*"@J*:FKJJJLKZVN+BXMK:VLKJZHJZBJJJZLK +M*RLKJZJJ:HJ*ZNKJZBHJ*VN+RTM+RXMK*ZOJB@H*"HIJJHN+ZVOKZRNKJZHJ +M*FKJ*JJJ*VN+BXN+BXOKJBIJ:NKJ*BKJZNKJZJLK*^OK*RNKJRNKJZLKZ^OK +MZROK*ZNJJJJKJZNJ*NIJ*JJJJZNK*^NK:JHKJJJKJ^OKZ^OK:VMK:^NKJBHJ +M*NIJZBHJ*BJK*BHJ*BJJJJOK*^OKZ^LK*ZOK:VMKZRNKJZHJZNJ*:NJJJJJJ +M*BHJ*JJK:XN+BXN+:XL+ZZJJZNKJJJNKJROK*RKJ:FKJZBHJ*BHJ*BHK:VN+ +M"PN+ZRNKJNKJZBHJJZNKJZJJ*JHK*^OKZ^NJ*NKJ*JJK*VMKBVMKZROKJJNK +MJBHJZHHJ*FIJZNHJJJJJ*FIJZBHK*VMKRTM+RTO+"XOKJNIJ:HIJZBJJJJKJ +M*BHJ*NKJZNKJJJLK:PL+RTM+"VNKJNIJBFKJ*FIJ:FIJZBJJJJHK"^NJZ^MK +MBXL+:^OKJBHJ*JJK*RNKJJJJ*NIJ:NKJ:JJK*^MK:VOK:^MKZRNJZFKJZNJJ +MJ^N+R\L+:VOK*ZLJ:HH*:FKJ*JKKZ^MK:^NKJRIJJBKJJBOKR[L[NPNKRCHZ +MNKJZNDIJ*TL[N\MKZ^N+"^LK*ZOK:^NKJJJKZVOKJRHJ*BJJ*NIJ:NKJZNHJ +MJBOK:VMKBXN+:RNJ*NJ*BHJ**BNJJ^LK*ZLKJZNK*BKJ:FKJJNN+BVN+"PL+ +MBVLK*FJ*"@J*:BHJ*JHKZ^OKZZNJJJJKJZMKBPMK*ZLK*ROK*ZNKJNKJJBLK +MJZNJJBKJ*JMJ"BJJ*JJJJNMKBXN+"VOK*^MKZ^LKJJHJ*BKJZBHJZFKJ:LJ* +M:NKJZJNKZVMKBXN+"XL+B\L+:^LK*ZOJ:HH*RKI*BNHJJRN+"XN+BXNKJNL+ +MJZLKJRNJJJJK*RNK*JKJ"FKJZFJ*ZNJJ*VM+N[O+B^NJJBKJJJHKJZLJJJHJ +M*JHK*ZLJ*JJKJNHJJJJJJJOK:XN+BXMK*RNK*ZLJ*JJK:HJKJZLKJJHJ*BHJ +MJJJJ*ROKZ^OKJROK*^OKJZJJ*JJKJJJJJJHJJJNKJZNKJZHJJBJJJZNKJRNK +MJJHJJ^N+BVLKJBKJ:FKJ*JNKJ^LK*RL+RROK*ZLKJZHJ*NHJZNJJ*ZNK:XN+ +MB^NK*FIJZBJK*VN+B^OKZRNJ*NKJ:HJ*BFHJJBOKBVMKBXNKJBJKJZLKJFIJ +MJBKJJBJK*^L+:VN+:ZNJZRJ**JJK*ROK:^LKJJNJZFJ*"HIJZNJJ*^OKZRMK +MBXN+ZVLKJBHJ*JLKJRMK:VOKJFH*"HIJ:JJKJZNKJZJJJJJJJJJJ*BNKJZOK +M:^OK"PLKZVOK:RNJZNKJZHJ*"LJ*JJLKZVMKB\O+RPN+ZZKJZFHJ*JKKZRLK +MJZOJBHH*"FKJJJNKJRLK*RMKBPL+:RLKJJJJJJJJJZKJ*BHJJJOJ*FLK*RLK +MJZNJJZNK*RLKZVOK*ZNJJBKJ*JHJ*BHJ*BKJBFKJ*JJJJ^N+BXN+"PMKZVLK +M*ZLK:XMKZRNJ*NH*RLJ*:NKJ:NJKJVN+BVOKZXMKJJJJ*JNK*ZNJJBHJZJJK +MJRLKJRIJZNKJJJLKZ^N+BPN+ZRNK*FJ*BBHJZBJJ*^MKZZNKJJJJ*FKJ*JOK +MBPO+2TM+RXLK*FJ*BFIJZBHJ"HKJ:FKJ*JNK*ROK:ROKZ^OK:VMK:XMKJRNK +MJZNJ*JHK*ZNK*BJ*:HHJJJMK:ZL*ZJNJJNN+*ZHJJZOKJXM+R^NJ*@K*BFHJ +MJJHK:XLKZZJK*TOJ8FHZ:NKJ*RL[R[N+R\M+"XOKZZHK:FH*RHKJZBJJ*BJJ +MZVLJBNJJZVOK*ZOKB^OK:PN+*^OK*HJ*BHKJZJHJ*JJK*RHJJZMK"PN+ZROK +M:ZMK:VIJ*XO+.X_?.R*&AD*^&D(K&[-#8^/#T^/[>Z-K"FKJ*DHZ^@KKR@LJ +M"XJ*JFHKBVL+ZBHJRRHK*XH*ZHHJ*RKK"JH+BFI*JZM+RPL[^\LJ"ZHJ*^HJ +M"NHK^VLJJ^JJZNMJ"JHJ2RMJJJJ+NRN*"JJ**^LJJRL+*DHJ*VJB:UO+VRNJ +M^FKK.KL+ZXM*2VM+JMHJRUNZBLI:2KI**WL[FWO[R_I**J,KZHIZF^M+.]LK +MNTI*ZN+JPFJJ@N/:&TK+2RN[ZWO#NVOZ2QI""L)#\BJ*.E,S`TNJ2\)K*JJJ +M:RN"JTK*RIMKNOOJ^LM+*_M+^^MZ>JOJJJKB&CN;&YKZV_IJ@_NO^@K**F,K +M6KZB^@-;6H^:CV]ZKRZ[>HKS#J^.4HL>#U+J`T+_`P./"A.""QH>*OZ"R@M3 +M"KL[@\/K<ZOJJ@HK2JN[HLO*VPMB8KHCKDNNBB]#,POC:V\*VI)N`Y*R\X+O +M,[Y/<NNO[H_:VO\J`^NN4EK:>XKRF\)+D\*+8^J_`\I;<B(JGEH;JF.:N[]S +M#ROK,UN[.ZZ>&OZ[R@YC`NO_.ZL3LD)S;BI[GIO[F@^#B\^[RZL;/AM+'G-Z +MGM.+FB<*.V?[HJOR#LJBQBK;\@^S0F,_4EM/DOOSPH)#V_)38SXOZ]YS>QY[ +M+ZY*SS*JORXZ[P+*0V)*4Q*ZW_+2#PLN`WKN<U*ZJYICV^LBX]M:`^JJZLN[ +MVX,"*S/28ML*RTLZ2SO*2SH:.EK[*[H[F^-[^INZBFH*^VZK.PIKN\JZLVJ* +MXPO:^R,:Z@JK"IJKFR+K8RO**HLZZS([;ZYK;QJBZKO[(TN#ZCKJFWH2FH(C +MBNL/"KJJBPONZTJ;`UHJ*]J"NX-**NI[`RKC&QOJFOJ*RZMB2SJR*MH*R^-[ +M8QLB2OKJRJK3:ZMCNQHZZXOZBGO[0J+CZNL**C/"OKJSXR)KOSMR^U-+VLJ[ +M*ZMZVFH:`LMSRGJ"`U.B^FM#@II/^Z)N`P]ZRUKNFNLRJ^^JJELK`UO:6J/; +M+I*BZGL*`[/;Z^L+:HH*2Z.;(JX+(QMN3F-3ZA(*C_.2$LL?<\[KLZO*8B*" +MJH)J\^.SJEJZ*ZJ[BJK[KS,R@NJ[@CHC8TM2*^,BPL**>\I;VPL+._,NKK]# +MHB)ZBFN+DDJ#FVOB2NI*;[\C*TJ[JNOZKEKRZTJ[$VH2PALS"EI;<_O;&SOC +MNK)R8H):0JOKNKN3C^]+&NN#N_KR(IK:JLJJ(L)+K\,[>PO+(]N[>L+B*SOK +M@NX:"RM*JXM[ZZICP^LZ*^O#.UIZ*SNB@BNCF\KZ.KNO(TK:"\M*>MH::BLK +MZBN3`\KBVGLC"VOZNNN+^O)*VZL*BWNC6PLJ:AK*B[H+(M+K8_LZ8].;*RI; +MZA+R:R.+BQL#.XKZZPOZTF[:ZDKJ*JK+TX^SZRKKJZNJ*@HZ.LKZ2NNKJBKK +M^^,["MH::DO[JXHK"BJ;.RKJJZMK2XL*2BN[B^NJ:RI:(KKK^SNK2CHK^TNK +M:JJKJHNJ>MKJ.SMK*\N[2RLJ*\O;F\O*^BJ+JR)"2LL[Z^M+"XNJBNM+J@H* +MZ\LJBBJ*&GKJ2YO+BVK*JROJRHJ+"^NK*[M+2_L[>^O*JLN+JVK*2KIZ@D*: +MZNN+R]NC^^JZZ@L[ZPH*:CN;.\LK*CJ:BHL+*OJZ:QNCV[O+"VNJ*FNJRKI* +M*SM;^ZH*.KI*"@JZ2LKJ*^OJ2BIKNWN;FTLJ2CHZ"LKZ&B):&OI*>CKKH_-3 +ML^.[ZZLJB_N[*RKK6Y-SX[MK"\N+JKH:FLIK(U//OT\O0UM+BD(^9K9VEA86 +MEO8&GK([#^='-W>7]T?G/_,[ZLHJ*BI+HR.;F]M;@Z/[BVJ:D@[^CAM'Z2EG +MBRZRZRL.]HBXN,@(Z*@V9DZ*_Y=IR<D)R;FY"5>G>RXFMM8H:(AHJ`:.*E-_ +M9[?W-P>GOR-BOA[^[D)"\C)BNLN?::$A>?=[^D./RG9X(.`@6)CXR.AV/C-W +M21G9>?EYF?F)!\O>]E8H:`C(".A&KK.G!S>7J>GIUP<OXI[FYN;F9H8F'FZ# +M*:%AH>E/\Z<'4\9XX&#@(*`8>$AHQNOWN9F9>1DA82&Y1V,R?L:H"#AX^,BH +MIJ(;KU_W:<G)Z7<G+VNROB;&=M:6MN:B-QEA(<E'YY>I)_Y((&!@X.`@H!@X +M*([G"?DY.1GA`8%9*7]+8KZV:/A8H)B(1DXR^C,':;FY":E'7R]+LEXVJ"@H +M=M[/2>$AN9<W:<D7(FA8(.#@8&#@(*!(9K\I"8G)F6'!P>&Y-\_C:DX6N%B@ +MF,BH]L8FXG^I2;G)*1?W1U_[_C96J)9&9L(W&2&9Z3>I"5>+5GB@(&"`@.`@ +MH#@V,]=IB4G9@4'!X3D7WQ.JGBAXH%CX".BH]MZ+9RD)R6FIUQ<W'SKF-C;& +M!H8F(PDAH<EWEPD)IX9(V"#@@`"`8J/J'URG)H8%!P6$9"=?GDPXHF*`8 +M.$BX2"BFF^>7*6F)B8GI-V\:#A[FMA;6-@X'66'9*1=)64DKB!C8H&!`,+!` +MX,A>NV]G">%!00%A(5FY%Z\>Z/AX>'C86/BHOFNO)]<)N3E)*4>?K^O.MJBH +M=J:J5UFA":E)69G?UL@(.."P\#!`@-CH9D*?R>'!`8$!00$9=Y.R9NCXH.`@ +MV,BH]F8J!^F)B0G)B5>';[I^A@9&%A9>?WF!V2F)H>')#@AH:*!`$!`PP.!X +MB+8#R>&!X8$QD4'9J>=O;N@8(""@F/@XB";O1[=W"9F9B?<')\-NAO:6EG8& +MVJGAX0D)(8%YRB@VMM@PT'"P0$#@.)9[Z1FAX4$1D0&9N0DG!KB8&*#@X-A( +MUKY[__<)>?G):6E7O_*^GL;6*/::J:%YQXD!`6G>!L,^X)#P@`!P<&#(MH(G +M:=F!L3$!88$A*8JF9BA88*!X^/B()AN?QZF)N?G)J4?G3V)FQF:&YMH7V4F' +M.8$9IQXZ\PA`0("`,)``>$C6.K>YH8'!P<'!X<E'#T)6>!AXV*`8")9F,L^W +MJ6F)"6DIE]][ZB+>!A[3Z?FIWQF!B:HN#^M80."@`)#P(+BXZ-*W21FA@;&Q +M8=EYR6?.EJ@(V*#8^#C(=A);CP?I20DI*:FWCZIBLF[.ZJG9%^^A89?;>^=N +M(."@8$!PL"`8^(A^-PD)6<$QP:'AX6E/2HYV>-AX>)@8N+;.DB,'Z>E7:0DI +MQV]O#UI.ZZEY=XL9@0?[S^<:&*"8((#P,"#8H!@&A\?'F0$!@>&!8;DW3Z,^ +M"'BX^%B@.%86QGK?-_>I"8DI]\<W;WJK<T?I*0_IX4<CQT\*:#BX(.!`L.`@ +MX!B6ZIM/R2'AX8$!@=G)*8<Z-JAH>*#8>#BX*!XBF_]WZ>GIZ>FIAQ^_0\]' +MZ:EOB1DOG^=JPNA(.*`@0,!8X"`X=JZKYXF9X>$A@>&9R:G'"J;&:$CX&#@X +MR*C&KNJ/MQ<I*>EI5_<WIP?I.7?C&4FRAWNN+CAXF-C@,.#88%A(1J*;APE9 +M(=GA@=GYN2F'*\YF%HAXN`@XR*@&WNYSIP>7%REI=\<WA_\'R4D_-R'G[[=. +MV^:8N'B@P,#8X"!XR'[*.T>Y67E9@2$9^0GIYVJNGA;(2`BX.(A61F9N0Y_G +M1U=IU]<I-_>)N;GWZ5FGIZ>>*RC8.*!@0``@@""8:#ZR8ZF9V9GA`2%9F4GI +M7VK")NA(R$AX^`BH]L92K[^G-ZEI5Y<I]W?I^3EG2:'OEQ\>CVB82*#@L`#@ +M@*!8:$Z^(RGY>=EA@2&AF3GI_WLZYN@("$CX.(BHUC:26Z\_!^FI=^DI%ZFY +M62DWX>G?:?ZS>EC(F"``L&``8"#81J:^7XF9F5D!@2%9&7E7#^.R!HA(R/B8 +M^`BHJ(:BVP\GERD7J>E7]Q=)&>GG63ESJ:MJXYA(2""`0.!@@"#8]N8FSVDY +MN5EA82%9V7G7'V\J9BCHB+AX.(CH*$8NZJ.?1U?7E^DI=U>)F4GG&9ESZ1NR +MC_A(""#@0&!@@""@5F;F$]=).9EA82%9V7DI9\]['JCH:+AXN`AHZ#;.&CM/ +M1]<75^DI5]<)V4FGV1E#Z1M"GWA(""#@0&!@@""@5D8&$Y?).7EA@:&AH9GI +M!Z>;?M8HZ#AXN,B(B);^4JM/!Q<7%VDI%W<I^7E'U^$'?ZD>IV98=IC@@``@ +M@&`@N+;60F>I.3FA@2&AH=FYUP?_(H96*`B8^+A(".C&_G(C)P=W*1=I*?>I +M%[F99ZDAWZ>IYN=F&,88(&``H(#@H+AVJ+*G-TFY66$A(2'9.2DW?YJFEJC( +M^#@XN,CH1B:N<Z='%ZDIZ:D7ES<IN2D_>4GK:9M:I_BH*""@`.#@@"#8*"A& +M+^=727DAX:&A(7D)Z<>/`F8VZ+@XN/BX"*BV)I*O)V<7Z:DI*5?W!T=I27_G +MH4__5X;')IA>>-@@8!C@(%@(%B@R/V?IR1FAH=FAV<EI%Z=[/@;6"+BXN+C( +M*#;F[F-_A[=7Z:DIJ;<WYT?)J7L)2=JIH^['N*BVH)A@H%C@6)BHJ+9C?W<I +MN=G9H1FAF6EI]P\K/N:H"`A(2+@(UG9FLL-_Y_<IZ:D7J9>GWV>IB0NGH9J_ +MET9W]K@">/A8H#@@6'CH%JBBKZ?W*7F9>1G9&0EI5Z>SKO[&:&AH",B(UC8& +MC@NO_X<WUQ>WJ7>G7W]G=ZD+=YF>%X<&5VBHKEA(V-CX()@X*"@6NLM_]^DY +M.9D9&7G)B=<G[UH^QBCHB,@(:*AVABZ*<Z<']U?7%Y=WI_^_\W?7"J<Y"O^7 +M9G<FB`NX2+A8R*#8.&BH*&Z*0V>7N4G)69DY.8EI1\]SPB86J"C(R&@H%C9. +MNHO/IT?WMQ?WMV>?3]N+PS?GGFGI?HF+2ZF(,JZX*)A(N*!XN"@(EE)R\Y_7 +M28FYV1DY24DI1S]C(H:6%N@(".A6U@9NVKOOAP<'ET>WQW_?TZIJJ^='OH?Y +M_I<W/@E&AL](J,@X"*!X.(B(:+[.2O_'"0G)V5DY.?EIU^>/>]ZV=B@(R&@H +MJ'8>\EKSIP?'Q_>WYZ=_;VI:"NX/E\Z_&;+WB3[)@C9?:"AHF,B@V)A("`BF +M?MH_9XE)2=FAV?EYR==';_N^=G8HR,@(Z"@6IJ[Z,Q]GA\>W!R<GSV,CVE(B +M#A^I)O=9#LG7PGG&'K_(5KAX2*#8F`A(:/Y.FW\W20GYV1E9.;D)-^>S>GYV +MENB(B(BHJ#;^+DH#OR<GAX=GI[^/,RI*.A)NLRFS(J%GSWGN::=H7W8(:-C( +M&*"8R&C()JXZ_^=IR0D9F7EY2<FIYS\;;H8V%NAH:"BH%F8.TBO3OQ^GAR=? +M7\_OL\O+ZY(:,W<GCGFIFOFK!_?H[UX(*'B(F-@XR"@(AO(N+Q_7B>DYF9FY +MR?FI!P<#RMY&QBB(Z.@H*+:FWL(+[S__!X<G)Z>GP_//ZNI:KK/7`\Y9YUJ9 +M+G=GB*>&"%:X:)AXR(@HB#Y"+G^G5VFI.?D)"<GIMV=_VZXFYC8HJ-86]D:^ +M<C)[;X\/__^/KP.3H^K[*GJZ&D)[UP<BF0GKF4_GJ:CC_DCH>$@8V#BXZ(AF +M8I(?!ZG)B3GY^<F)B<>?;V+N!O8V**C6=L;F+@J+4_^G'Q\?KX/K8H(.;N[^ +M0O+.4RDWV]F9KUF7MVGV@ZXXB)AXH""8>(C(!IJN?[<I20GY>3D)B>FGOW.R +M#D;&MJ@V1H;>3@K[(X]__P^/[\NZXFX.?OZ23N[JZ@>IK^E9IXG)WZGZ;@KH +M",@XF-@XN&@H-AKB4Y>WJ4EIB<FI*1=?OR]Z[FXF9N8&'AY^XN+JVQLS,P/C +M2TJ",HX.#FYRLMIK>R^'-\<I:=>I]\??BP*>]NB(R#BXR(BH=B9RBM.G1Q>I +M*>DI5Y='?R\[(A(^GAZFGCYNDEKK.X.S0S,;"ZNB,M+N;@XN\G(KWT<O5[D? +MZ>D?EVH:RA:HZ&A(2.B(UC9F>N(#)^<W]Q=7][<W9\^/DTLBPH)NSFX2TJZ: +MZBJKBZ.+JTO*(K*2+N[2,EJ:JF,#TW_GIV=')R<?;Y,K`NZ>9D9&]C;&!J9^ +M;AH*^S-S#\_/OX]OKQ,SVR/;B\L+BRMK2ZL+2^M[F[M;6_M["RJZ&CI*JQ/J +MXR?*[_^:0T(N$B8FAN8&!GZF#K):(X/OGY]?WU^?3P\3PYO+RRIJJJJJJHL+ +MRSL[NXOJ*KHB@I+NCLY.SHXN\J*ZRZ.S[X\/3\\/CZ^3PUM["ZI*FIJBXMI: +MXAKZ>DJ*"BIJZJMJZNJZNGJ:VB+B8J(:>CJ*JFM+>UOC(X,#8^,CHZ,;6R,C +MH^/C&QL["RL*:NJZBJMZ^HH:HH+",I(2KE*NTH)BVHJKR]L#L[.S<W,#@\-[ +MNSL+RVLK"VMK:VOKJFLK*JKJ:LI*ROKZFGHZ^HJJJXO+.SN[>_M+BZNK"LI* +M.DJZ2HKJ*VO+R\L[.TM+B^LK:FK*.OJ:(L*BVMI*ZNM+.]M;(V-C8V,CVWL[ +M"XMK*ZLJZFKJ*JJKZJOK*JJJ"@I*^OK:(N(B(B+:&AHZ"NJKBWL;6R-C8R.C +MVWM+2PMK"XLKJ^J*RLKJJZOK:VMK"PMKBXOKJVJ*"LJZN@H*R@J**JJJZRNJ +M*RNJ*ZMJ"KHZFIHZ2HIJZFN+2[L[.[O[FYN;VUM;HYO[NVNKZHI*.OIZ>DK* +MBJKKJROK:^NKZZJ*"CKZFAKZFGHZRFHJ:TL[>WM[^[M+2\O+2TO+2\M+2\N+ +MZRNKJNIJBNJ*RLK*NOKZ.OHZRHKJJ^L+RTM+2\O+RXMKZZNKJJJKB\OKZRLJ +MJJKJ:FH*"@H*:NJJJROK*ZNJ*BJJ*VMK"\O+N[O+RPN+:RNKJNIJ:FH*"HKJ +MZNHJJJJKJZJJJBJJ*RLK:^LKJZLK*RMK:RLJJJJ*"BKJ:BHJ*JHJJROK:VN+ +MBPO+"XMKBXN+BVOK*ROKJJKJBHK*2DK*2KK*BNHJJJOK:^OKZ^OKZ^OKZZNK +M:VMKBPN[^_L[RVLK*FH*2KJZ2BIKZPO+"PMK*ZMJ"@H*RDK*"FIJZBHJJJNK +MZ^MK:^LKJJLKZXM+.WM[F_N[B^LKJZHJJJHJ*BKJ:HJ*"@H*:HH*"@I*2DK* +MBFJJ*VMK"TL[R\O[N\L+BPN+:XN+ZRNJZNHJ*JJK*ZLJ:HK*2DK*R@IJJBMK +MR\L+RXOKJZJKJJJJJJHJJJNJJZNK*RNK*ROKZ^LKZ^OKJRLKJZKJBHJ*B@JK +M*RJKJZOKZZNJJZNKJZNKJZLKZVMK:^LK*RNK*RNKJ^LKJZHKJRKJ:FKJ*BKJ +MZJOKZVN+:^OKZVMKZ^LKJ^KJ*FKJJJLKZVOK*ZLJZNIJ:LK*ZFJJ:VL+"VOK +M*ZLK:XN+BVOKJZJJJBHJJBKJ*BKJZNKJZBKJZBJJJ^MKBPL+"PMK*ZHJZHJ* +M:NKJZBJK*VMK:^LKJNIJ:NHJJROK:^L+.TMKZZLJ:FIJZNKJZJJJJJJKZFKJ +M*JNK*^MK:XMK:^LKJRNJJJNKJZNK*RLK*RLJZNKJZBJJJJHK*ROK"XMK*RIJ +M:NKJJBOK:VMKZ^LK:RMJ:NH*"HJ*ZJLKZVN+:VOKZ^LK*^OKZ^OKZRNKJJJK +MJJJJ*BKJ:HIJ:FKJ*JHK*ZNKJZHJ*^MK:ROK*ROKZVMK*ZNJZBHJZNKJ*JJJ +MJRNJZ\O+BPN+Z^NK*BJJJZHJ*FIJ:HJ*:NJKJROKZ^LKJZHJ*BJJJJHK*VN+ +MBXOKZVMK:RNJJBHJ*NKJZNHJJJKJZJLK*ZLK*ZNKJROK:XN+:XOK*BJJ*BKJ +MZNHJJJNKJZNKJJJJ*JJKJRLKZ^MK:^MKZRNKJZNJ*RNKJJJKJZNK*RNJ*NIJ +MBHIJ:NHJJ^LK*RNKJZLK*^MKZ^LK*RNKJZNJ*BL+ZZJJZNHJJJJJ*ROKZRNJ +M*BHJ*BJJ*JJKJ^N+R\O+"XOKJRIJ:FIJ:BJKJZNKJZJJJRJJJBHJZJLKZ^MK +MZRLK*RNK*^LKJZJKJJJKJRIJBKJ*JJHK:VOK*VMKBVOKZROK:VOK*ROKJZJJ +M*NJ*BHJ*:NHJ*JJK*RLKZ^MK:VMKZ^LK*^LKJRIJBHKJ*BJJ*BKJZNHJ*RLK +MZVOK*^N+:VN+2^NKJRJ*:NKJZBJJJJJJ*JJKJZNKJZHJJROKZRLK*RLK*RLK +M*ZNKJZKJZFKJ*JHJ*BJJ*RLKJZNKJ^N+"\O+"VNJ*NIJBHIJZJKKZVOK*RH* +MZBHJ*NHJJZLK*ROKZ^MKBXOKZZLJZFIJBFKJJJNKJZNKJZNKJJJJJBKJJJNK +M*RLK*RHJZBHJJBMK:XN+BXL+B^LKJBIJB@H*BFIJZJJK:TMK:XLKJJJJ*ROK +MZROKZZNK*BHJ:NKJZNHJJRNKJRNKJJJKJRLKZ^OK:VMK:VMK*ZNJ*NIJBFKJ +M*JJKJROKZRLKJJJJJRLK*^OK*RNK*^LKJNOK*ZNKJBHJZNKJ*JNJJNKJZNJJ +MJJJKJJHKJRLK*^OKBXN+BXN+:VOKJRKJBFHJZNHJJJJJ*BJJJZHJ*NHJJJJK +MZ^N+BVOKZ^OK*RLKJ^MK*BJKJJJJ*BKJZNJJJZLKJJJKJBJJJJNJ*^MKZVMK +M:^LKJZKJ:FKJZBHJJRLKZ^MKBXL+B^LK*BHJ*JJJJRLKZ^LK*ZHJZHJ*ZBHJ +MJBLK*NHK*RN+BXN+:XN+Z^OK*RNKJJJKJZNJ:HH*RFKJJFLKJBMKJZMK*RJ* +M:BLK*VO+BVN+ZZNKJNIJ:HH*RFKJZJOK*ZNK*^OKBXMKZRLK*BJ+2XN+:RNJ +MJJHJZNIJ*NIJBFKJ*JHK*VN+BXMKZRNKJBHJJROK:VLKJZKJ"@H*B@J*ZJJK +MZXL+R\L+B^NKJJJKJZLKZVMK*ZNJ*BHJZFKJJNKJ*RLKZROK*ZJJ*BJJJJLK +MZ^LK*^LK*ZNJ*NIJ:BJJJ^MK:^LK*ZNJJBHJJJHJ*JJKJZJK*ZLK*RLK*^MK +MZRLKJRNKJZNK*ZLJJNIJ:@K**JIJ*JNJZVMK:^MK:XMKBXOKZRLK*RNKJZJJ +MJNIJ:NKJ:NKJ*JNKJJHJJROK:PL+BVOK*ZKJZBHJ*NJJJZLK*RLK*ZJKJZNJ +MJBJJJJLK*RLJ*NNKJJLK*^MK*ZLJZNKJZJJJJROKZVN+BXN+ZZHJ*BHJJZJJ +MJZNJJJNJJBHJ*JHJ*JHK*RLK*ZOKZZOKZRNJ*BJJJJJK*RNKJZKJ*JJJJVMK +M*JJJZBJK*^OKZ^NKJRNKJZNJJJLKBVMK:VOKJJJJ*RNKJJKJZFKJ*NHJ*NIJ +MZBHJJBMKBXOKZ^OK*RLKJZLK*RNK*VL+:^NJ*FK*"@K*2@JKJZOK*^OKZVLK +MJRLK*ZLJJBJJJRNKJJLKZ^MK:RNKJJNKJJNKJZNKJZJJJJNKJJLKZRLK*ZJK +MJZJJ*BHJ*BHJJJJK*RLK*RLKJZJJ*JH+"^N+:RNKJZJJJNKJZNKJ*JNJJZNK +MJZHJZNHJJZNK*^MKBXMKR\L+"PMK*RNK*FIJBHIJ:FKJZNKJ*BKJ*BJJJJOK +MB\M+2TL+RPMK*RKJBCJZ"HKJJJNKJJNKJZNJJRJJJZLKZ^LK*^LKJRIJBNHJ +MJJNK*RLKJZLK*ZJJZNKJ*JHKBPL+"XOK:RLJZNKJZBHJ*JJK*ZNKJZNK*RNK +M*RJJ:^NKZRNK*RLKJZLKJZNJJBHJ*JJKJZJJ*FIJZBJK*^N+:VL+B^NKJNJ* +M:NJJ*RMK:^OK*RNKJBHJJJNK*^MK:^NKJBHJZNKJ*JJJ*VN+B^OJ*JLJJZNK +M*^OK*ZNKJ^IJ"FKJJNL+"XN+:RLKJZHJ:FKJ:FHJJJLKZ^OK*RNJZNKJZJHK +MZ^OKJRLKJZLK*RNKJJNKJZNKJZNJ*BKJZJJJ*\N+Z^NJZFIJB@H*:BHK:PL+ +M"PN+BVOK*RNJ*BJK*^OKJRHJZNHJ*FKJZFIJZBKJZJNKJRLK:^LKZRLKZ^OK +MZ^OK*RNK*JJJ*BKJZBJKJZLJ"FJJJROK:XL+"PN+BVOKJ^KJ*BHJZJHJJRLK +M*ZNKJRIJZFH*BFKJJBMKB\M+2TM+B^NKJNIJ:FJ*B@J*:JJK*RNKJBHJJJNK +MJZNK*VMKZPO[RVMKZRLKJZNKJBHJ:FJ*BHIJZJJKZ^NKJJJJJJJKJRLK*ZNK +MJZLK*ROK:VMK:^LK*ZNKJJJJJJJKJJJJJRKJZJHJJJJJJBHJ*JJJ*XMKJFHJ +M*NKJ*JHKZ^MK"XN+:VOK*ZNJJZNJJZNJ*BHJJJHKZRLKJZJJ:HIJZNKJJJLK +MZVN+BXN+:^LKJZNJJJHJ*NKJZFIJ:FHJ*BKJ:BJK*ZN+2PN+RVMK:^NK*VOK +M*^OK*ZNK*NIJ:HJ*"HIJJBOKZRNK*^OKZVMK:^OKZ^MK:^LKJZKJZFJ*ZNHJ +MJBJJ*^OKZRNJJZLJJBLK*RNKJZNKJ^J**JJJ*JJKJZJJJRJJJZNKJROK:XMK +MZRLKJNKJZBJJJJLK*RLKZRLK*RNKJJJJ*NKJ*BHJ*JHJZJJJJROK:^LKZVMK +MZ^MKZ^LKJZNJJZNJ:PNKJBH*2DK*R@J*:BJJZXL+"PO+"XMKZZLJ*BJJJRLK +MZVLKJBHJZFIJBHKJ*JOK:VN+B^NK*RLKJZNKJRNKJ^KJJZJJJFJJ:VOKJZLK +MJVH*:BLJZJMK2[N[BVLKZHK*2HIJZJNJZHIJJBN+R[M+Z^HJ*^MK:^MK*ZKJ +MB@IJJJKKBVOK*ZNJ*BJJ:LK*ZJKJZNL+BPN+BZMJ"@J*ZBL+R[N[RTN[:RKJ +MZNKJ2PHN6HHZ@_LR3HLGVT)ZN]\GXC9*I\_["R[F#X^2?@8JG\<#ILH[;B:2 +MC\=_OB9R:^JK^X.?QW>G0EX.BK*>_H)S8SH.LJ)*D_OJ4T\SBA*.ZALKFX^_ +MCR,R[N*K[GX.>B]3+TH*K^\[CH+""J^C:DJS.TLKLNK:DA):ZJ\OJZ)Z(^-# +M:YKJ:YL*"VI*P_LJVMHJLOKZ8HLKHXJ+TQ./Z_J*HH(BHC(*(S/SBZJKZZNB +MHDHKJLL;ZDJJR]LKJ\I*N\NJB@I**BJ*RGM[6X.;RX*2`HM;ZVI:ZCMKR^J+ +M:RN*>F*ZH[M+>[-[FVIZ*@JC*KKZLBNB:FH*$[.#NJ***LN:*GJ*@QN[RFNJ +MBNKJJPL+B\NJ:IJZRRIJBFK*BQNJBDK+VVN*6HN+JZO*JMIKVTN+BTL*JSHZ +MZLJJ*WM+N\OJ2RNJ"LJKJIM+JSJJHXM*&@JK"@OK*RN**XL+JKL+*LIJ*J(Z +MRHKK:KOCH\M*JFM+"ZI*VDIJ"SLKZFJ+"TLJ&BJ+.ZOZ"HM+BFN+RZN*:XK* +M*OMKZ@O+R^J*"HJ*"@J*2SLK*[MKJNMJVDH+"^MKB_O[JPJJ*NJ+:^HZRJJK +MJBKK:ZJKBRKZ^DHJRPMJZ@O+2ROJ:NH+RWL+JBM+.VNK*RNJBDIJ:LHZ>@H* +MBYMKJXKKJHI*^JLKB^M+VYO;N[OKJNMJ:GI*:HKJRJOJJHL+J\JKZRKJ*FOK +M2TL+RZHKJ@HZ.JIJBNJJBVMKZROK*JKJ*ZMJ:\N+JVN+*TO+JZJ+:ZH*RNHK +MJ[K**HOKBKK**XOKJ^JJZ^NJJVN+"XLJJ@OKJBMKJBJKZLJ*:BIKBVO+BVLK +M:BH+*PHJZJKKZUH.+@*:Z@O[6R-C8V-C(Z,;FSN["XLKJRKJBHH*RDI*2DI* +M2LK*R@J*BFKJZBHJJJNKJRLKZ^OKZ^OKZ^OKZ^LK*RLK*RLK*RLKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +:____________________________________ +` +end diff --git a/share/isdn/4.g711a.uu b/share/isdn/4.g711a.uu new file mode 100644 index 0000000..cf431ad --- /dev/null +++ b/share/isdn/4.g711a.uu @@ -0,0 +1,322 @@ +begin 644 4.g711a +M*JOK:XL+R\L+ZRN+:VKJZNHJZNHJ*BIJ:NKJ*BJJJJJK*^OK*RLKJ^MK:RNK +MJROKJZJJJBKJ:NKJ*JJK*^LK*VN+"VN+BRLKJZNJ*JHJJJJJZ^LKZ^LKJBHJ +M*@H*ZFIJZBHK:VMK:VN+ZZHJZNKJ*JLKZVN+BPL+BVNK*HH*BHJ*:BJJJJLJ +MJZNKZ^LKJRNK*VMK:PLK*XNKBJJK*BHJ:FKJZJJJJJNKJZHK"\MK"PN+BVN+ +MZRLKJJKJBHH*"HIJZBHJ*NHJ*JHKZ^MKZVMK:XN+B\L+RXLKJZHJ:HH*"HJ* +M:NJ*JBLKJRLKJ^OKZRLK*ZJJJBJJ*ROK:^MJ:BIJZJHJJJJKZ^OKZROK*ZNJ +MJJJKZVOKZ^OK*ZJKZFIJZBJJJJJK*VMKZZOJ:FIJZBHJJRLKZVN+:^LK*^LK +MJRHJZBJJJJNK*RNKZFH*BJJJ*BOK:XL+"XN+BXN+*RKJZBHJ*JHJ*JJJJJJJ +MJ^OKZZLJ:HJ*:FKJJ^N+"\O+"PL+BRNK*ZLJZHIJZBHJZNHJZNKJ*JLK*ROK +M:VMK:VOKZBHKJJLK*RNKJJJJJJJJJJHJZNJK*VMKZ^LK*ZJJJBHJJJKJ*JJJ +M*^OKZ^MKZRLKZROK:^NKJZJJJZNJZBJJJBHJ*NKJJBJJJBLK*^OK*RN+ZZJK +M*ZHJ:@H*"FHJJJNKZVOK:^LKJ^N+"PMKZ^LK*ZNJJJLKZRLKJBJJJZLJBHJ* +M:NJJJROKZ^LKJRLK*ZNK*ZNKJNHJ:NJJJRLKJZNK*LJ*ZFHJJ^OK"\M+RPL+ +MBXMK*ZKJB@H*RLH*:JOKBXMKZRLKJZNK*NHJ*JLK*^MK:RNKJZJJJJNJ*BJK +MJJJJJZHJ*JJJJRHJJJLK*ROKZRLK"XLK:^NKJRLKJBHJ*BHJJJJKJJJJJBKJ +MZBJJJJHJJJHK*RLKZVMKBXN+B^LKJBHJJBIJBHJ*ZBJKZVN+BXL+R\L+:RLK +MJRLKJZNKJBKJ*NH*:BIJBNKJ:FKJ*BJJJRMKBXMKBPN+BPN+ZRNKJRHJZNKJ +MZNKJ*JJJ*JJK*ZJJJZNJJJNKJROK:VMK:RLK*ZNKJJJJJJJKJZNKJZJJZFJ* +M*FLKJ^LKJZNK*ZNKJJHKZ^OK*ZNJZFJ*:FKJJBMK"XMKZRNKJJHJZBHJJBLK +M*^OK*ROKZZNJJJJJ*JHJJJNJJZJKJZOKZ^LK*NIJ*BHJJBLK*BMK*VMK:XN+ +M:VOKZ^LKJNJ*"@H*"HJ*ZBJJJROK:^MK:VMK:^MKB^LKJZJK*BHJJJHJZFJ* +M:HJ*ZJHJJJNK*^MKBPO+R\O+"PL+:RNJ*JHKJFHJZHJ*B@H*"@J**JJK*VMK +M"\L+:^NKJZLKZVN+BVMKZZNJZHH*B@H*BFHJJBHJJJJJJRLKZXL+BPMKZRLK +MJZJKJBJJ*JLK*RNKJZNKZLIJ*NHJ*JJK*^MK"PN+BVMK:XOKJRKJZNKJ:NKJ +MJJKJ*JJK*NHJZJHK*^MK"PL+"XOK*ZIJBFKJZBHJ*FIJ*BJJJJNJJRLKZROK +M:XMK:VL+NXLKZZLJ*NKJZFIJB@J*ZBJJ*JOK*ZOKZVMKBXN+:^OKJZJJJZJJ +M*BJJJZNK*^OK*RNKJBIJZNHJJRNK*RLK*ZNKJZJKJZHJ*JHJJBOK:^NJZVNK +MJBHJJNKJ*BJJJZLJ*JHKZVMKBXOK*^MKZRNK*ZNJJJJJJBLK*HK*"FIJZNKJ +MJBMKBXO+"PL+BVLK*ZNK*ZKJ:FJ*BFKJZNHJ*FJ**NNKJXMK:VN+"XL+BXN+ +MBVLKJNJ*BFKJZNKJZBHJJJJKJJHJJBHJJJJJ*VMKBPL+BVMK:RNKJZNKJBJJ +MJNKJZNHJJNOK*ZLKJZKJ:NKJZBIJ"JIK:PO+"\M+"^NJZNKJ:FIJ:NHJ*JJK +MJJHK*^MK:VMK:VOK:VOKJZNK*ZNJJBKJZNHJZNIJ:FKJ*JJJJJJJJRLK:XL+ +MRPN+ZVOKZRNJ*JOKZFIJ"@J*BHJ*:BJJJRL+R[M+R\N+ZZLJ*JJJJJJKJZHJ +MZNHJ*BJJJRKJZNHJJROKBXMK:VOK*ZNKJRNKJZHJZFKJ*JJK*ROK:^OKZ^LK +M*@KJ*BJK*ROK*ZNKJJHJ*BJKJZNKJJJJJZLKJRIJBFKJ*JJJ*RLK*RLKJZLK +MZ^OKZ^MK:PL+B^NKJZHJB@H*R@J**JJKJJHKZ^MK:PN+*ZMKRVN+RXMKZZKJ +M:HK*RHIJZNIJ:FIJZBJK*RMK:VMKZ^MK:VMKZ^NKJJJJJJHJJJJK*RNKJNIJ +M:FKJ*JJJJ^OK:^MKZZNKJZNKJ^LK*ZNK*ZKJJJHJJBJJJZLKJZJKJZNK*^OK +MZ^LK*ZHJ*JJJJJJJ*JNJJZNKJZLK*^NKJBHJ*NIJZJHK:XL+BXMK:RNK*NIJ +M:NHJ*BKJ:FKJ*BJJJZJJ:POKZVOKZRLK*^OKZVMK*^OKZRLJ:HH*"HIJZBJK +M*RLKZ^MK*ZJJJJHJZBHJJZLK*^LK*RLKJZLJJJNK*ZLKJZNKJBLK*^OK:RNJ +MJZNJ*BH*2FKJZJJJ*ZNK*^OKZ^LKJBJJJBLK*^OKJZJJ*JNK*^MKZZHJ*BHJ +MJJOK:VNK*NJ*BNHJJNKJZFHJ*ROK:VMKBXN+ZRNKJBJJ*JNKJRHJ*NN+*RNJ +M:FK*R@J*ZJIK:XN+:^OK*ZLKZRNKZXN+:^NK*NKJ:FIJBFKJJZNKZVMKZZKJ +MZBJKZXN+:VLKZVN+ZRIJ:HIJ*BHJJZNJJZLKZZNJ"DJ*BNHKZ^OKZRMKZ^MK +MZVOK*RNK*ZNKJZOKJNOKJRNJJ^JJZBKJ"FJ*ZBJKJXN+:VOKZ^LKJZHJJVLK +MJZNJZBOJBBKJJRLKJRJKJJHK*BMKRVOK*VJJZJNKJZNJJJJK*BJJZBIJ:BHK +M:XO+"PL+*^OK*^NK*BIJ*NJKJRN+Z^LKJNIJZNKJJNHK*^NJJNHJJRHKB\L+ +MBVOKBXLKJZIJ"KIZB@KJJZHKJVMK*^OK:RLK:XO+BROK*JHJJHLK:RKJZFJJ +MJBHJJZJJJXMKJZKJZBJJ*FHJ*JLKRPN[N\N+JFJ*:FK*2LKJJXN+R[N[NXNK +MJRL*BNK*2@H*BHO[RVNJ*NJJ:RLJ*JKJZXLKJHH*ZJMKBVLKJFO+RXNJ:FJJ +MZXLKJZIJ*JLKJRKKJFJ*"HHJJ^J*ZNJJ"_M+ZZJJJXN[NXOK:RMK:\NJ2OIZ +M*NMKZKKZ.JHK:NHJ:^OKBXL+N\L+:ZOK:ZJ*:JKK:XLKJBJJJJJJJRNJB@I* +M2HHJJBHJ:VM+>\OK*^LJ*FOJJVLJZBHJZ@M+JBMKBZMJ*BK*BJNJ"PLJ:BIK +M:RNK:BKKZ^N*:BOKN^L*ZHL[NRMJ^DKK6]LKRAI**HHJJBKKJZKJZTO+.^MJ +M:CM;:WI:6JK+"RLJ*ZOJF@H[>XMJZHN+ZFNKZ\O[>PJ*JBNJZNIZ"@MKJFKJ +MBZK*:BJJ*ZHJZLIJ2SO+:RN*"YM+BZMK*^J["XL+.KIZ>KK*RVHZ*@J+FSN+ +MRDHKNQL[^^NZRHMKRHOCJSHJ.HH+ZZJ+2QKBJZHKJBJJZPM[&^MK*LH*ZRLJ +M2JHZ@HJJ6^/[:AI*"LL+*RLJBVMJ2^MK*IKK>SOK*BMJR@KBRLO;2[KZ^OJK +M"PLJ*NN+>TOK*HM[J^IK"WMK:VO[2VJZNHOJ.CJ:^LJ[VRO*JHH:NJMK:XMJ +MRFL#8XN*RNMK"XNKJFHZBHIKN^MS6R)B<AJZFPL:"KM[^PMK.UNCNZK*NAHJ +MBXN*BFM;ZEJ::KL+"^NZBXM:>NK[&[N[RRIJRROK*SHB2JJZ*ZIK>QN[^RKK +M^QH*JGHB&FLK2^.J>FL+NX-K"EIR@HL#FXOK:[LK*\MK"L*:RV,;NAKJX_.; +M"GJ*RH*2RGNC@RNZNNJC0QNZHAJZFVNZRKO[:PN+:WKB(IJ*(V.;H^H*JZH+ +M:YMJ>HIK"[L*XAI::N.CNGJZ"^.+ZHHKRRLKBNL[*ROJBKOC&^KZ&F)*FSNK +M"CIJ2RKZZ^-KRBK*"]M[*MJ*FOK[`R.:DHJJBV,[JXOKNGH;,^OB\HMS>[I" +M0CK;.[L;R[IBLCIC(R.J"AOK*^JKJTKK:VK+6PKR0KIC<YOJ&@J+Z[MJHGJK +M:XNC*_IZV\.Z@OI+F^L*HMHC4V.JNLKZJQNK>BH+^\K:6KIC2ZJ+^FOK:LM+ +MB^KZ*_LCNT*2>JK:ZM,OKT.B$AH+"\+B6@K++X]JLC*R:KO;6ZMKFNOK:_.3 +MXQIB>DMSHS)N&IOS6SH"`LM;:^JJ*[I**J.C^\H*B[JJZDJ+^EI"6ILS$R,+ +MRHNJ^F)""LLO#YO:"KKB*DNJ:H/+ZZH*BMJ:.H/#&S(N.IJZ(JI;@\^SB^O: +MXI+:8Z];BZ*:*ANS(PK.PB.;(_MZJKJZ2V,CJH(BRCL;BPH2;@(;`X-KNE)* +M@V-#*X/S2\KN[OOS(VL*8IJBZCN[(\O[^JMKBOOJ:EK""\-+BBLJZB.[^N)Z +MJN-S2\JRJ\,[<L+J"WOC8VIZ`CH*V[,KNPNOD[+.'B/S\H(NZ]M#KXH#P^]# +MLKK:0J+JJFK"FI.;0B*S0X.3"BYNHNHK6SLJF]MS+RNZJ_N;CM+RNAO:.OJ# +MSR^SBV("J[M:JII2RONO$YM;VD*:FNH"J[M[(^O+B@HZDK(BR^.[2^K[KV_# +MHPINPF)*8Z\SR\*^[M+OWPOR+JX+CT^*+@*:WW_Z;JYB^GJ[*^-C&_L3TY-Z +M$@(2NR/+<E)BNAO+>L,[VCNJ@^\/_\):*A):/CZ"6BO*>R]O0WL;\THBNAN3 +MXTLN;B+"RD.SZRZNNB,#OP_+XOKZDBLO;PK*KCY*0X_J&LZ2L@O_@\J>[NN+ +M0P./AV_CRPJ:V@JSBZZB2C):,V(*J\ZJDC+R.A\:RX]S@QNS(NZ""@,3[P,N +MPB,";IK;MV>C[C:>'@(/+T/KH@OO3_-R\J+["\M/+_K"SCYN0FKN4K)39R>/ +MFUN"^]JFVLNC6F*O:VLJ2C("AT>G6Q+^'NZRZY/?HQKN)GX:\T,OJ]*2;EL_ +MSR]K"EKZ8W-O"M*:8ONS\WJ.4K,/^R[BZS)B4EMO>W-J\DXR`Y,_KR/KH\LR +MHBY^TNOST\_S>M+2(I*OHZM[2OMJXCI+H]LS7P\[;J;.OJ[Z@X]S<PMC$[,+ +M^LKRHJ*"^HI+*KMJJX_+JJ-JRDIK.X+N(NL*FX^C8T.+LOXN[LJ/\\OZHJK[ +MDZ,#&Z*RP@+*2BO/ST,O8TX28H[:ZRJ##Q]_2Z;^>CH[KB[BRN./GT];^G). +M_D[*"DO;[R>?3Z(NKG[N\DI+8W^_`Z]+PO("*PM+HWN:KDZ&)M+J#^=G/V_3 +M@^JB(AIZSGXNJL-;<R\OT_K2<N)ZX@H#D_O*2R,;,WMB(H(::XIB\KJJ"FH* +M*^/[^GM3&TIZZZJB.M/_KR/Z+F[24O)[$R_S8]/3<SKN?I["BJ,CBNHC+T-* +M+B[*DZ\3XPL"3GZ.NJ.C:\M#TX\S*RI*$FYBJWNCKV\OTUN:PB):`M)"8BYR +M@HHSSS^#RN*"RY-SNVO;2XKBHNK+"RNB,KI+6V-C*L+RDH+*RZ,#0\-S\WNJ +M&L)"0J+**\O[*S(^_J[ZVU.OKR-:TO+"^F,_W]]_?S_O0\L:+D[.[GH3AZF) +MR8EWLX;(H&#@6$B6/BK#$U.O+R_OS[\__S]/CV^/CX\_']^GYX>')\]+<B8& +MKQE!D9%AYUA0C,R,4.`6VO]GMZD)66%AH8EOQDAXN*B>2Y]G!S?7J=<'K\[6 +MB(A67ALG-S>'WQ-K2AKBKCIIL:TMK6&S`&R\/`P0>(KWB8GI*6DYV7GIKT8X +MH)@H$F<IZ9>G#X^_G\\+?I8H*+8R?Q<I*7>G`WIR3AXJ>='M;:W9%JP\G'P, +ML`;IV>&A^0EI2<D7PY;8@&!X'C>9(5EI'[H./F[2CN8V]@8NKS<I*7=?FZ[> +M)EZK>:T-#>UAYE`\'!S,\-:I6>$AF4D)R0E'XHC@0,!X@DD!L0'Y'UZHZ*A& +M)AZFGA*;IW>IE^?#CK8HZ*@.^>T]?;V1XQ!\I*3\K&AI8<$!(7E)20D'SOA` +M$)!@YDDQ4=$!B;JHN#C(Z%;VYL)O=XE)B3>SGE;(N`C6_S%-?7T-X;@,7"2D +M3,#[(;%Q02%Y20EWBNA@D-`PN!]A$:WQH<>>:+A(B.A6-MYJIZD)"=>_+M;( +M^+AHHH'-?1T],<9LW"0D//#2(?$1,>%YB2G'HNA@D%#P^$_A$:UQH6?FB+@( +M*';&Y@ZKWU>)B1</CE;(^/@(DF$-?1V]L09LW"0DO#!*X?$1,>$YZ5<G$FA@ +MD%`P.*>!42UQH1^6^!@XZ/8FOC)CA^G)"==OGNCX&)A(MNFM/9V=;0D`/*3D +M7&R8:;%14;$A25?G&A98L-"08":Y\:U1P8FN"!B8R%:&_BZ*#_=I"6E'FX:( +M.'@X:"_QS7V=#2%XS%PDI`S@-\'143$A"?<GBD8X`'!P@)8I0:VML3DKB%B@ +M^"@FLBKC3\=7*5=G.Z:H"$BX"'8WD<W]?8V9H$Q<)%R,V(GQK:VQV:D_&\YV +M.("PL*"FB4'1D8'I+@@8F`CVON)JV\]'J>FI9^N&:#AX.&@*@8T]?4W!=NP< +M)*1,P/]!K2UQ(6G_Z_Z62"#`0.#VEX'1T;&Y"@@@('BHOGN/_Z?'%U=WWTJ& +M*`C(B%;&;P%MO3T-`7;L'"2D3`#G,2WM$>&IBQYV:+@@@(#8IBD!$1'!"5(X +MX."85M)O9P>'AT>WAV^B9JB(R`@HAJG1S?W][6D`/*0DW"PH(:UM+4&YCYXV +MZ,C88`!@B$\A$:T1X3\(8$"`N!X_]Q?WAX<'9W]K'M:(R`@H!IHYK4T]O='G +M,/RD)'P07H$M[:T!::M&*$@X6&!@V$:7@=&M\9F:>`!`X&B:M^GIEV>GG\^C +M<H:HB`B(UB:CH>U-/4WQ2M!\I*0\L-,Q[6VM81=.*$AX&"!@(+@NR4&MK4$) +M9B"PL""HT^E)R:EG3S-[2H[&J&AH*+8^6[E1S4U-T:>P/%RD?)#NP>UM+0&I +MCF@X&!A8(*`(KFD!$=%!"9Z@0+`@J,,I2<FIYX\#.^H2YA8HZ*BV3HH'@>W- +M36TAZ.R<I%R,V`E1;6T1F;,H>%A8F!B8"&8G63'1<2'?",#PL-@FM_D9N5>? +MN\+N3B:VEM;VYB[+KP<AK8T-[>'&K/Q<W`P@UQ%M;=&9R\B@(*#X2(C6OJ=Y +MP9'QX<?H`/"P6.9W&:'Y5V_"?M[>)L8V-@9><B-/GRG!+6UM$:F@C)S<_-`& +M82UM+0$'J"!@(/CH%C;>2Q=90?'!2?)8L/``B*\Y(:')YR(FQ@;F)B:F'H[B +MRQ.30U?!+>UM<0=@S!S</#"+L6V-K:'*.&!@V.@&AF;^B_>AL7'!B29@D'"` +MEK>A@2&)+Q[VEL8F7I[^#L)KKT_O.V^9D2WMK7EH[/P<?*PVX2UM+6&3R.#@ +MF"B>SB:&CC])`7$QV;L8\-"PN*]Y@6'Y)S[6Z%9FCB(Z*ULS4U/;0AY>Q[$M +MC8U!NI`\W-P,>$FM;2W!)^B@(+B6;JZ&5O8BJ6%QD8%'"+#0<*#RR>%AF<>. +MUBB67B*+N[M[6V,CBV*^IGZWL>V-;<'R$/S<'(RXN5'M48&?*)AXZ&;23O9H +M**ZI89$1`?=H0!!P('XIH2$YAS(&1B:NJ_M+*KJ*Z\LKNGH:LJH)\2WMK1DH +MK#R</*QV&=&M<:'O%DC(J,8F1BAHMO.YP9&1(;\X,-#P6`XIH2&95V,^!L;F +M?F[RNAL3+Q/[&J[.CB[O(:WM[7$'X`Q\?,P`_T&M44&)#H@X"*@V-JAH*.[7 +MX7'1,4EF@-#00(A?V8'A.6<N-M9V9@ZB2_/O;W-+HJZNLKI*BVDQK2W1>2BL +MO/R\T+89$5'QV:_6.+AH%L8VEA;>I_G!<3&AL_BP$#"86@DAX9F7J^;V]@:> +MPHOS#T\O>PHBPH(:(CX^U[&M+:W95JP\_+R07B%143$YFHB82"C&WH9V5J:G +M>4&1\:&C&/#0\!AJN6&!V1?Z1JBHMOZB>V]_GX\;6@Y^OE("\LXJ>1$M[9$I +MV&S\_`R`_\%1$8&7ACB8")8FG@:6]F)7(3&10<FFX'"0P&A_>6'A>;>:!M;6 +MMJ;2:^\?'V\+4J;FGD(+`VM"QP%1+:WA_G!,_+RL5GD143'YXLB@F.AF(AJN +M#MKGR2$!@;FZ.`"P@`@#R:$A.<?B!G8VYHY:Z]M#DS,C*]J2[FZ.[HY^IL\! +M+6WMP:*0/)S\+'8AK2UQ^:;8@""()OM#ZD)*IXFA@6&Y^PA@P.!H0PFAH3G' +M@K:HJ+;^FIL3CV\S"]K2#@Y28IJ*BI(.=S'M[5%YR&Q\?,P`MW'MK8$?N(`` +M6';K)Z<S.@MGB1FA^7?N"%B@2(8/Z3DYB0>JYM8H5H;2FX__/R^;^BX^?KZN +MRK,/CTLNCR$147$9QA#,3(P`WT&M$>&/^```6+:O%Q??JK([Y^FYN5?3INC( +MZ`:J9ZGIJ6=[_K;6E@:.:X_?W\^#.NY^?@Z2"K-/O[,N!J,AT:UQF790S$SL +M(*GQK?&9;B#`@+@2MVD7,YYF$C_I>?DICSZ65K:>2E/?9^>GCVN.!I:69K(O +M9\?G4^*FQ@:>@F/_)Y\STO;HLB&M[5$A!M!,3&R@:7&M,;EF8$"`2,K7"9?+ +M9C8>\REYF8FG$D;V9HY*0[^?IR=_\^+FUJ@VK@\WEV?+)M8H=LX#)T<'GWLN +M9M:H.N&M[=&A)I#,#"Q8*;&1P>GV8,#@*._I"4?2J&BV^RG9H?FW$G86)KK_ +M!V?_0RN:HO*>QO9&_KO?A]_KII96Q@)_]U<W;Y+FQ@;FIBO9K>U1@5,`C,QL +ML,IA\4'Y^M@`X$A"=VEWRA9H=NJIV>%9J8M&*/;N+X>WQY_[PKZ&-O9&7CH_ +MYR=3<@86EN;J)W>7Q\\ZGH;F3F)Z2D<!K='!Z>@0C.P0",G!05F?B&#@./ZW +M">F/MD@(9I\YX>%Y9U[H:/:R'Q>IEQ\BAM:H%N:"K^=G#Z)F5JBV+@^7Z5>G +MBMY&1GXJ#Q]3:F?A\3$AQT@0[*Q`9GD!8<D:."`8*`N7*0?2*,AV.^FA85DI +M2E8(J![#Q]>7)_N>-I9V!HX[3U__FXX&M@;NLV?WQT_JSJ;^6I.GYT_ZYH;G +MX3'!&:_8$%!P6.\9X7DG]IB8B$Z'*:F_)FCH7K\)6=G)9ZYV5L:N+P>W!\]: +M)G;6-MYZ+U^?`T(F1@:^BY]'1]\C(HX.XMO/W_\;OG:VI^$QP1G3&'#0\)C/ +MF:%)C]:8^"@B-^E7#^;H*#X?"1D9R>=.J.AV#B]'=[<_0L96J+8.8Z>'WQL. +M!C9F@@\'-V<3&@[^TKL/_\\C0EY&-O*)`4'A*>9@\+`@9JEYN6<>"+BH#J=7 +M%]_N5FBVJC=)>4D7&P8H5B9+!ZFIQYMF*&C6?L-G1R>CC@8V9A)#IT>'[UK^ +M'JX;_V=G3XH>-A8VFHF!`:$7)J``@)BFMXFI+R;HZ,9ZY_>'<WX65J:S%[GY +MB><2=BB6#B\WJ9<_KK:H5F9Z_\<'3YJF1L:^"Y^')V^K[O[N*E,?)T^[;H;V +M!N,)X>$YI_98X*!H^C>I!ZH&J!8FZZ>'ISM^ML;"GU?IU^?K'@:F@M,G9U^3 +M>DZF)OXR:Q._SX.:CAZ>THLOS^^CFO+BJO/_GR]*/H:&LL<YV3F7@FB8>`BF +M;X>G^_ZVMI[*[[^OBDXFGBJ?MW?'OZON_DZ:+R=G7R^KKO[>_J[*8Z]3@ZJ2 +MOC[N^J.OTZ/KRGHJ6U-O4POR3@XZGZF)Z4>;ANAHJ"8J#P^;<J;F?H([`UM* +MKD[N"E.?IY_O&XHZZJ,O;U/#6TNJNL(N4B(K6\/;RG)NKN*KPU.SFZNBLJ(K +M@U.OP\M*8D*Z\Z?'!Y^[;N:&)NY*NPNBCGY^#B++6]O+:KJ*BYO#\_.SHTL+ +MBVN+^]N;NRNZ&IJZJKN;FYO[NXL*HB*ZJ\L[^\MKJZH+^SOKZOI:V@K;+T\_ +MST/*4K[^;K(::BI*6L+R\D*"HDHK.]M;&Z.C&QM[RXMKJBK+FQNC&[OKRMKB +M.LMC@]M+J\HZ2HJ+VZ.;2XN+:ROJ>H(RXKHJ2^/S$[.;ZVJ*ZHHZVJ+:^KJ: +M6J("\I(2,AHJ:XN+:VN+:RN+2SM[VP.OCV^O$S,#H_O+"PO+RVLKZOKB@F)B +M(N("@B(:^LJ**JHJJ_N#0Q,S.THB(EIZZLN[Z\H:X@*"`K("VDJK"TMKJNKJ +MBZ.O#^^3@UN;VP/S4].#.^OJ:BKK*SJR+HZ.;JX"^JN+ZZHJ*VMK:\N;(^-; +M&TMKJ^KJZJLKJFJZ6F)B8L)"8AJZ*NMK"SN;6UL;6V,#0\/CV]NCXZ,;&YL+ +MJHHZ^@HZXJ)Z^CIZX@):>GHZRNHKZLJ*J\M[>PMK"[L["PN[RXL+JHHJJ^JJ +MJRKJ2GJ:VIK*JHN[>WO;FSM+B^L+NPO+N_N;>[N+B^LJ*HIZ.DKZ&AK:VLHJ +M:NJKZFJK:LHJJZMKBRN+2[N[2VLK:^NJJZLKJ^KJZVMKBXN+BXNK:NJ*RHIJ +M"NJJJJNJ:FKK:^N+BXL+:VMKZZOJ:FKJ*BKJJFOK*BJ*"NJJBFHJZJJJZBM+ +MNVMK:ZL+RVMKR\L+2^OK"ZOJJ@K**^NJJRIJ:LKZ^CH*ZNKJJRMK"^NKZPO+ +M"VLKBPMK2TL+2\LK*JKJ:FH*:FIJ:LHZNDJ*ZJHKBTL[.TL+"PMK*ZJKJJLJ +M:FJ**JNK*RNJ*ROJ:NKJ*JJKZVLK*VMKZRNK*^LKJJJJJJNK*FIJZFIJ*FH* +MJNNK*^LKZ^LKJVMK:TL+:XLK*NKJZNIJ:NIJZJNJ*NL+:XOKJZLKZHIJ:NOK +M*VLK*XM+BVN+:RMKZZJJJFIJBHKJZJHJ:FJJZZKJJBOK:RN*JFOKJZJ*ZBLJ +M:JJJJHOKJFOKJNMKJBNJ:JL+"TL[BZOKJZIK*ZHKJJJJ"@HJB@IJ*BJJJVKJ +MJZJK*RLK:RLK:XL+2\N+ZZLJJHIJZJJKZHJ**FJ*JJHJJRHJJZLJ*JJJZXMK +MB\N+*ZNKJXL+ZROK*VN+JRJKJBNKZJHK*FJ*RFKJJHNK*VOKJJNKJFOKJJNJ +M*JJJ*BHKZ^MK:^OK:RNJ*ZJJZ@J*:HHJJRLKBVL+2\N+:RLK:RNJJJHJJJHJ +M:HKJJBHK*ZOK*^JJJNHK*ZKKBVL+RVMK"POKJNIJ*BJ*"@H*BHH*"HKJ*NNK +MJ^MK"POKZVM+RPL+N\L+RVLKJRLJBDJZRNKJ:HJ*JJLJ"LJJJZLK*^OK:ZLJ +M*RMK2RNK:VMK*^OKB^NJZHKJZHI*RFJJJRJK:POK*VOK*^OKZNHKZROKZPO+ +MRPNJ*NKJ2DKJJZMKZ^N+"ZLJ*BHJZHH*ZBJJJJOKRXNK*ZHJJ^HZ2NKJJ^HJ +MZPN+2\L+.[N+:^LK*ROJZBHJ*JIJZJOKJZNKBJOK*FK*"@KJ:JIK:XL+"PO+ +MBVLK*RNKJBOJZNJ*BJIJ*JLJZNNK*XNKZTLJ*HNJZBN*BJLJZXOJZBOJ:BKJ +MZJLKJJHJJPMK:^OK"[L+*ZOK:^NJ:BKKJZK*RBJJZNK*ZNNK:NHJZ\L+*ZN+ +M"^OJZJHKZRLJJPO+ZRLKJBNJ"JJJZBKJR@KJ*JLK*RMKZRNK*ZJK*^OK*ZJJ +M:VMKZZJJ*ZNJ*NJJZ^NK*RLJZVH*ZBIJ:NHJ*RNJ*JNK*ROKZ\M+RXO+"\MK +M*FIJ*BJ*BBKKJBJ*RHJ*:NJ**XNK*BOKB[MKZVL+"XNK*JNKJ^H**BLJ*FIJ +MJBLJ:NHJJVMK*XN+:VOKZXMKZRLK*ZHJZJJJJBJK*BHJ*BJJJZNJZJN+JFHJ +MJNN+J^HJ*XO+BXO+NPOKJNH*:FJ*ZBKJZJLK*ZNK:BHKZHIJ:NHKZZOK:^L+ +M"POKZXOK*BHJ*ZNJ"@JJJRNKJVO+BXLKJNOKZBNJZJHKJFHJJJOJ*BHJJJMJ +M:NJJZFJ*JFN+BXMK:^NKJZKKZZLJJRNK*JKJZXMKJXN+*RLJ:NIJZHH*ZJNK +M:XNKZPOKJROJ:JHJJNLJZ\MKJZNK*RLJ:BHK"XLJ*JJJJZO*"BJJJRHJJNOK +M:RNK*RHJ*BHJZ^OK:^OJJ^OKJZNJ*RNK*HIJJJHJ*JLK:RNKZZJJJVJ*BBJJ +MJZNKBRNKJZLK:ZNK"TLKZZLK*VKJZBJK:RNJ*^LKJRKJZNIJZNKJJRNK*JMK +MRPN+"XMK:^NJ*^LK*RLJZBJ*ZHI*NDI**JLKJRNKBPOKZ^OKZROJJ^OKBPN+ +MN[NK"JNJJJLJBNJJ*@I*RFJKJVHJJVN+B^M+2[L+BRL+RVNJ*ZOK*ZLJJZKJ +M:LH**JLJ*FKJZFIJ*JNK*HL+BVMKJZNJJ^HK*JHJJBHKJZN+"[L+JJHJ"HHJ +MJJNKJ^MKZROKZXL+"ZOK:ZLJZHKJ*JMJ:HKJ"LJ*JJHKZZNK*VOKZRMK"XN+ +M"VOKZRIJ*NJJJZKJJ^J*BBHK:^OK*JNK*RHK*JIK*ZKK:VNJJZHJJ^NJJJJK +MJZNK:ZKJZJOJJJHKZZNJZNHJJFHJJJMK"VMK:POKZZHJJVNKJ^HKZXNKJNJJ +MJBIJ:HIJJJLJZJOKBVLJJZNK:RNJZPLKJVNKJVNJJBIJZNOJJZN*JFNK*ZLJ +M*XNK*JLK:PNK:NJJJZJ*RNLKZRNK*\MK*VLJ*BJ*"NIJJNOKZPN+:PL+:^OJ +MJVOJJFIJ*NK**NJ*J^LJ*RLKBVOKZ^MKBVLKJROJ:HHJ:BIJBJJJZJLKZXO+ +M*VN+ZRLKZJJK*ZHK*VN+B^NKJRN+J^NKJZNK:FH*BLK*BJJKJBLKJBKJJ^LJ +M*ZNKZ^LJZRL+"PLKBXN+*^NJ*^NJ*FIJJFLJJNJJ*RLJ:FKJ*JKJ*JJKZRNJ +MZ\M+RPOK"\OKJJKJJJMJ:JHKJZNK:VOKZROKZZLJBDHZ2HH*:JLKJROK:VMK +M*^L+*VLKJRL+:PL+JNLK*HJ*"FH*2@KJJXLKJHO+*RLK*ZOK:BHKJBKKJZN+ +MZVOKJZKK*NKJ:NKJ"@JJZZOKJFL+:\O+BXO+Z^KJJZHJ"DK*ZJNKZJKK:VMK +MJXL+ZVLKJRL+JRNJJJJKZJLJ:NIJB@KJRDJ*"FJJZNKK2TN[RXO+RVMK:VN+ +MBZJK*ZLKJXKJ:JHJ2KJ*:NHKZZOK:XMK*^JKJZLKJXKJJJHKJVHJ*ZOK*^KJ +MZZJKJBJKBVN+*ZHJ*RHJ*VLK:PNK*BIJJ^OJ:JKJJRK*BNLK*ZMJ*ZNJJVLJ +MZXO+:RNKZRNJ:JKJJZLJ:BNK*RLJ*BMKBVLK:XOKZRNJJZIJZBNJ*RMJBJJK +MZBLKJBLK*JJJZBOJZJKJZBKJJVN+R[N[2\N+*ZJ**JLK*RLKZVJ**@H*JBKJ +M*BIJ*JKJZJHKZ^NK:VO+:ROKBPN+ZZJJJBH*BHKJ*JLK*ZNJJZOKBRLK*RJK +M*ZNK*ZLK:VLJ*BHJJNIJZFOK:ZLKZ^LK*FKJ*ZKJ*BJJJFHJ*BIK:ZOKZRJK +M*^NKJBOKJZKK*RMK*RMK*ZOK*ZOK*ZLKZRJKJNKJJBOKJVHJJJOKJNJKJXJ* +MB@KJZHHJJVO+"\M+"RLKJ^KJJRJJ:VMKBZOJJJKJ:@I*"FJJZBJJ:\N+*VN+ +MBXMKZBJJJ^MKJRN+:ZOJBNJK:JKJ:BOKJJNK*BOK*JKKJNLK*JN+*ZIJ:JIK +M*FJJ*JLKZBHK*^NKZFHK:VOK*VO+R^NKJJNJJBHJJJLJBDH*:JNJJZKK"XOK +M*JLK:ZLK*ROK*ZLKJZJKJNKJJBKKZ^LJ*JHKZZNK*^N+:RNK*^OK*ZKJBBLK +M:@KJJZLJZNJK:ZNKJROKJFIJJRNJ*NJKBZLJJNOK:VOK:PN+B^MKZROK*RMK +MJZNJ*BIJ"DIJBNIJBNJJ*BLK*RL+:RNKZVMKBXO+NTO+JRJJ:@JZ2HJJ"@J* +M:BHJBHJJ*ZOK*XO+"XL+NTOK*^OKZ^LK*NNKJNJ*"NIJ"@KJ*BJJJZJKJ^HJ +MZNMK:XL+BPN+BXN+BVLKJROJ:BJJ*HKJZFKJJBIJ*NJJJ^LK*^MKZ^NKBXOK +M*RHJJZJJ*NHJZFIJ:NJJJJJK:PO+"XOK"PMKJZKJJJKJZJLKJNKJZJJKZHIJ +M:FKJZJOK:^OK:XO+NXMKRPN+ZZNK*BJ*2HIJZFIJ:HHJ:NJKZPMKZROK*ROK +MJROKJNOKJBJJZJJJ*BKKZ^NJ*ZNJJZOJJ^NKJNNJJZNJ*ROKJZLJJJLJBNHK +MRVLJJNLJZFKJJFN+"RLK*ZOJ:NIJZNKJ*BJJ*ZOKZRNK:^MK:VLKZZLJ*BJJ +MJ^MK*ZNKZHJ*B@HJJRKJJBJKJVMK"[N[RPL+ZZLJ:BKJ:@J*ZBLJZJLKJZLJ +MJJLKJBMK"PO+R\O+RXMK:^LK:FKJ*HJ*BFKJZFHJZBIJJJLKJZJJJJJJJJKK +M:VOK:PO+"XOK:XN+JZLJZFH*"FKJJRLK*^NK:NHJ*BNKJJJKJZNJJJMK:^NJ +M*JJKJJJKZVOK:^OKZ^NKJJNKJJJKZZNKJZJKJNJJ*ZNJJZHJ*JJJJZNJJBIJ +M*JNKJZJJJ^N+BVMK:VOK*^MKJZOK*BJJJJJJ*BJJJRIJ:HJ*ZNHJJJNKJ^MK +MBXL+"\N+BXMK*RLKJJHJZBJJ*JHJZBHJ*BHJ*RNKJJNJJROKZXN+:XOK*ZLJ +M:HI*2LJ*BLHJ*ZLK:PN+B^LK*RLK*RLK:VMKBVMKBRNJZBIJ:@H*BFIJ*BHJ +MJJJJ*VMKRPL+RXLK*^NK*JNKJJJJJBJKJBHJ*NHJ*NHJ*FKJZNHJ*VM+.VOK +MB^OK*ZNJJBNKJBHJ*JLK*ZHJ*BJJZBHJ*BJJ*JJK*VO+2TO+"PMKJRJJJJJK +MJFIJZNIJZNHJ*BJJ*JNKJZNJ*JLKZ^N+BPN+:ZJJJNJ*JBLKZXL+BVLKJJHK +MZHH*RDIJZNIJ*JOKJZKK2TM+FYN[J^IJ*BK**BJ**JHJJVMKZRLJZFH*NCK* +MBNKKRPL+RSO[FTL+.PNJJHH*NGK*:JI[,[(^JJ,:!C8G5[HJWUL[I\K6CM<Y +MKDAV;ZE'7OC>_\_ZRP?"]G9J%X<GVZ8*?R.F!B9[]P<_FWKKI\.^FC(."DM: +M3MZF`GJ+SW_[0MIJ<\^#6VH3C\^OR^O:CDY.9E+3F^+J&V_OZG*J`HLO>WL: +MLX/[HXJKFCK.\@.SLVH^/FKS_Z\CKJYJJ\,:BJ-#6[*Z:ZN:0K(2(K/#>[LC +MLR\36JOO2[(NK@+*R@IK^XK*PZ-KHCL+HGJ"R[/;"ZXJ,_-C8BLKJSJZRYKJ +M&NJOXVN:VEI*J[K:NZ-+ZHKZRO/OHP*"&\L+:K+SKPMRDIOJ*CH:*TI+NMK: +MZJ^[BRMJZYM;JFI*FIN36XJB"HK**LOJFK(ZDS-K(KJ[B^LJBFO;RQIK.ZM+ +MJJ(BZWM[BZ*B:AO[ZVOJRZMZXJ**(BK[R^,;(R-;F\KBRML+6FJ:NFN;&[I* +MZHHZF]OJ2KJKNSOJ*MM[B_I:2R.+8H*Z.T,[>J*J(_LZ(@(*RPN[*ZIJ*]MK +M"LK[6XN*>HH+.\KJ.YN[ZBH*"KHZ"XH["QJ+.[N*^GJ:B@H+:RJ;2TLKJRM[ +MRRJ[JRHJ:\LK:J+*N[O;:GI*RKI*:ZOKZ_M+NOJJ>ZN:6NK;>\OKR^NK"JI+ +MJCJZ*ZJK:PLKF\LJB\O[BCH:NJN+RZIK"JO[:VJZ^HHJZRM[>TN["LHJZVH: +M.NKJ:FLK:JJ+B^LKZ^LK"JHKRWM+B^M+"ZIJ:LKZ.FKJ*NNJ"JL+"ZJZ2HL+ +M*^J[6YL:CJX"&FJ+.]NCX^/C(Z-;FWN[2PMK*ZLJZFJ*"LK*RDI*2LK*"@J* +MBFIJZNHJJJJK*RLKZ^OKZ^MKZ^OKZ^OKZRLK*RLKJZNKJZNKJZNKJZJJJJJJ +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M__________________________________________________________\` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +:```````````````````````````````````` +` +end diff --git a/share/isdn/5.g711a.uu b/share/isdn/5.g711a.uu new file mode 100644 index 0000000..03fe03b --- /dev/null +++ b/share/isdn/5.g711a.uu @@ -0,0 +1,368 @@ +begin 644 5.g711a +MZVOK*RNKJZNKJZNKJ^LKZVMK:RNK*NJJJNJJJRHJ*BHJJBOK:^OK*RLKJZNJ +MJBKJ*BJJZ^MKBXMK:RNKJRHJZNIJBFHJJZNJ*^MKZRLKJZHJ*JJKJJNK*^MK +MBVMKZZLJ*BHJ*JJKJHK*:FKJJ^MK:XMKBXMK:XMKZ^OKJZJJ*NKJZNIJBFJ* +M:NJJJZLKZ^OKZ^N+BVMK:VLKJRNKJNKJ*BJJJJJJJBKJ*JJJJJJJJZNJJJOK +M:^OK2[MK:^NJ*NKJZBHJ*NKJJRLK*RNKJRIJ:NHJJJNK*RNKJJLK*^OKZZNK +MJZLK*^OK*ZJJJJNKJRLKJRNKZ^LK*RLKJZNKJRLK*ZNK*RNJJJIJ:JKJZBJJ +MJJNKJBJJZBJJ*^LKZXN+:VN+B^NKJJJJJROK*ZNK*BKJ:HH*"LH*:BJJJRMK +MBXN+:^MK:^OKZVOKZ^OK*RLKJRHJZHJ*BFIJ*JNKZJHK*VN+BXOKZZNJJZJJ +MJBHJ*JJJJ^LK*ZLKZRLKJZNJ*BHJJBJJ*^MK:^NKJBHJJZNKJZHJ*NHJ*JJK +MJRMKZRLKJZJJ*BJJJRNK*ROK*JKKJZLK*^OKZVLKJZJJ*JJKJZNKJRLK*RNK +MJJJJJJHJ*BJJJRLKJZLK*RLJZNHJJJJJJJLK*ZNJJZLJJJNKJZJJZVOK:VMK +M*ZLKJZNKJJKK*RHJ*FIJZBJKJBLK*ZNKJ^OK:^LK*RLK*ZNKJZNJJZLK*ZNJ +M*NHJJJNKJBKJ:FKJ*JLKZ^MKBXOKZ^NJ*JJJJJJJJJLK:^LK*ZNJ*NIJBLIJ +MJRHKBXN+B^LK*RLKJROK*RNJJJLJJJNKJBKJZNJJJJJJJJHJZNJJJROK:VMK +M:^OK:RNKJJJJJJNJ*NIJZNKJ*NKJ*JNKJROKZVOKZROKRXOK:VOKZZNKJZKJ +M:FH*"HIJZNHJJJJKJRLKZ^LK*^OKZVN+B\L+:^LKJRIJB@H*BHKJZNHJ*JHK +M*^OKZ^OKZROK*^NKJZJJJZNKZRNK*ZJ*BHH*:NKJJNOKZVOKZVOKZ^MKBXN+ +M:VOKJZHJZFJ*BFHJJRMKZ^LK*ZNKJRHJJJJKJRNK*RNKJBHK*ZNKJNIJZBJJ +MJROKZ^OKZZOJ:FKJJFMKZPN+:VOKJZHJZNHJJJHJ*BJJJBIJZBHJJJLK:^OK +MZRNKJZOK:VOKZ^MK"PL+:^OKJRJ*BHJ*"@IJ*JJJJRLKZRLK*ROKZ^OKZRNK +MJZNJ:JKK*RLK*ZNJ*NKJZNKJZBJJJJLK:VOK:XN+:VOK*ZLJ*JJK*ZNK*BHJ +MZBKJJJJKJZNK*ROK:VOK*RNKJJNJJZNKJZNJ*^MKZROK*ZNJJJMK*ZNKJBKJ +MBHJ*BFIJZBJJ*^OKZROKZ^N+:XMK:VNKJZJJ*NIJ:NIJ:FKJZNJJJBMKZ^MK +MBVN+RPN+BVMKZRNK*NIJ:HJ*:NKJZNKJZNJJ*FHJJRHKZVL+BPM+2[M+BRLJ +MZFIJ:NIJ:FHJ*BHJ*BHJ*JJJJZNJJZLK*RN+:VMKZRLK*RLK*ZHJJBNK*JKJ +MZFKJ*JHKZZLKZ^LK*RLKZROK"VMKB^NJZFKJ:NHJZFIJZFIJZBJKZ^OK:^LK +MZRLKJZNKJJOK:XN+:^NK*BHJ*NKJZNHJ*JHK*ZNKJRMK"PN+BVOKJRJJJJNJ +M*NIJZNJJ*ZKJJJLJJJNJZROKZZNK*RMKBPN+B^NKJJJKJNIJB@K*"HKJJZJJ +MJJJJJJNKZRLK*^OK*^OKZ^LKZ^NKJZJKJJHJBFKJ*BHJJBOK:VMKZRNJJ^NJ +MZJJJJ^MK:^OKZRLK*RNKJBHJJBKJ*NIJZNHJZBHJJJJKJJJK*RMKBXMK:PO+ +M2PMKZZLJZNHJZNKJZFH*BLJ**BJK*ZLK*RLK*RLK:XOKJVMK*^OKJZNKJJHJ +M*NIJ:FIJZJJJ*^OK:XL+BXN+:^NKJJLJ*BHJ*BKJ*BHJ*NIJZFHJZFKJ*JNK +M*VN+2\M+R\L+ZRNJ*BKJZFKJ*JJJ*JKKJBJJ*BJJ*JJJJRNKJRLKZRLK*VMK +M:VOK*ZLJ*BHJ*BJJ*RLKJJHJ*JJJ*ZNJJJHJJJNKZVOK*^OK*RNKJZJJ*BHJ +MJRMKJPHK*_HK2\KJ:PJK"ZLKBRNJ:VNJZTN+R\LKJBIJ:NHJZJJKJJLK*ZHJ +MJZJJJJNK*ROK*ZNJJJLK*ZOJZNHJ*BKJ*JHJ*BJJJJJK:PO+RPN+BRLK*ZNK +MJZHKBRLK*ZNJ*FIJ:HJ*BFIJ:NHJZBJJ*ZOKBPL+BXN+BVMKBRNKJZHJJJNJ +M*JHKJZJJZBHJ*FIJBHIJJBOKZVMKZ^NKJZLK:VLK*^LK*RLK*RJ*ZBKJ:HJ* +MBHIJZJHK:PO+"PL+BPL+:^OKZZLJZFKJ*JNJJBKJ:FJ*ZNIJ*JJKJZMKBXMK +MZ^OK:^LKZRNJJZNJZNKJ:FHJJBJJ*^OK*ZNK:PLK*VLKJRLKJBKJ*JJKJZNK +MZNKJ:BHJ*JJJJJNK:VN+:VMKBVOKBVNKJZLK*^LKZRNJZHJ*:NHJJNKJZJHJ +M*BHJ*ROKZZNJJ^MKZ^OKZ^NJ*NOK*VMKZ^NK*NIJZBHJZNHJ*BHJ*BJKZ^MK +MZ^LK*RNK*^OK*ZNKJBHJJJJJ*BHJ*FKJZNJJJJLKZVMKBVN+2\O+BXOKJZLJ +M:HKJ*JJJ*BN+JBKJZNKJZBJKJBLKZRLKZVMK:VOK*RNJ*BKJ:FKJZNKJZBJK +M*^OK:VOK*ZJJJROK:^MK:RLKJJNJZNKJZNKJ*BHJ*JJJJBJJJBLKZ^OKJJMK +M:VN+BVN+:^OKZ^OKZRNJ:HH*R@H*BFIJ*BJJJROKZVMK:^NKJJNK*ROKZ^OK +M:^MKBVN+:RNKZHK*2LH*BFKJJBOKZ^OKZVOK*RNKJZL+"VL+B^MK:RLKJBKJ +MZFH*:HIJ:FIJZNHJ*JLKZ^OKZ^MK:VN+BVMK:^LKJZLJZFKJ:HJ*:NKJZNIJ +MJBMK:XN+:^NKJZNKJRLK*RNKJZJK*^J*ZFKJ*BJK*^MKZ^OK*^OKZVMKZ^OK +MZ^LKJRKJ*BHJZNKJZBHJ*BKJZNKJZNKJZJHKBTN[N[O+RPL+B^NK*FJ*:HJ* +M:NHJZFH*"@H*:BJK"POKBPO+2TO+"XN+:VOKZRNK*HH*BHH*2LJ*ZNJJJRMK +M:^N+BVMK"PN+ZRNKJBIJ:NKJ*BKJJBNK*NKJ:NHJ*BOK*RN+BRMKBVOKJZIJ +MZNI*"JNJJNLK*^LK:^LKZZNK*JLKJBOK:VOKZVOK*^KJBFJ*ZBJJJBOK*^MK +M:VLK*ZNJ*JNK*ZNJJRIJZ@IJJZHKJVMKBPOK:ZNJJRHJZNHJ*NMKJZHJBLH* +M2LKJ:FIJJBMKN[N[NTM+R\N+:VMK*RNKJFIJBHJ*:NKJBLK*"HHJ*BOKB\N+ +M"XMK"PL+"VLKJBKJ:HIJ:FIJZNKJ*JJK*VOKZBIKZVMK*^LKJRNK*^MK*ROK +M*ZLJJZNJZHJ*BHKJ*JNJJVOK:VOKZ^OK*ROK*RLKZ^LKZRNK*ZNJZNKJ:FIJ +MZBHJJJHKZXN+:XL+B^NKJJN+ZZLKJZJJJBHJ:@K*RKI*RHIJ*BOK:PO+R[L[ +M.TO+"VOK:RNKJBIJBFKJZBKJZNIJ"@J*:BJJJJJJJVL+R\M+N[M+RPN+ZRLJ +MZHJ*RLJ*BLIJJBHJJBHJ*JHK:^LKZVMK*^MKZRLK:VMKZRNJJZIJB@J**JNK +MJJNKJZNJJRNKZRNKJ^LKJZIK:^NKJZLJ*BJJJRHJZNHJJJJKZVOKJZJJ:RNJ +M*RLK*ZNK*RNJZVMKZRLK*ZNJZNKJ"@J*:FIJ*JHKJROK:XN+BVMKZZLKZXN+ +MJZOKZZNJJJNKJ^IJB@J*ZNIJBJHKZ^NK*XL+:^OKBXLJJBLJ*BKJZJMK:ROK +M*ZOJ:FIJ:NJJ*^LKZVL+RXOKZRNK*FHJJZNJZNJJJBJ*BFIJ:NJJJNLKJRLK +MZROK:^MKZ^OKZ^OK*ZLJ*NL+JBJJJ^OJ2@KJJRKJ*JOKZRNJJBOK:XMKB\L+ +M"PMKJBHJRLK*"HIJJRLJJBMK:ZNKJ^LKJJHKZ^LJ*NMKZROK:XLKJFH*.@JK +M:FJK:JJK*XO+"[N+*FOKJVLKJ^NJ*BHJZVNJJRKJ*ROJ"JKJBFIJJNIJJNL+ +M"\OJ:@O+RVMK:^LJZ^N*:NHKJVKJJJJJNTNB.FHJJDHKJ^OKJRJ+BVLKZVN+ +MBXL+B^NKZBJK*FNJ*ZHJ*BIKZ^JJN@JJ:ZL**NJ+ZRO+:^M+R^N**JJK*VKK +MJZLKJJLK*RH*BBNJZLH*JJIK.SL+"VO+2^NK:HI*NHJ*J\HJ*VHKZ^KJJNIK +M*VHJ:@N+Z\M+.[MK"BK+:VL["XJ*JFNZ&FJZ2BHKZNNJZ^OK2^LJNTLJBJHK +MZNL+JBKKJZJ*.YLJFJL*:XJ:NBH+*NHJ"PL+"ZOJ2\LK.RHJB[J*ZLOJ>FN[ +MR\JJ*VL;J[H*ZFJK"XMKJ[MKZZM*:NJ+NFJ**DMJ*FHKZPN[JBI+Z@J*XJKK +MRBL;B^LJ:TM+2ZKJ:^MKB^IZZ@JKJBOK"BOKZRKK*DO*2KH*"EIJ:_N+:_OK +MH[L*:QO+:LJJ2^J:FBN[R[JZ.WOJ>CKKBXNJ2BNJ*[N+*TJ*._N+:@H*2_NZ +MFFKJ"LJJZVNJ:NI[^^J*.BN+>ZOJJALC\PORBII:"JJK:ZN;.\-/NJ;N4MJ" +M\OJC+^/;DX];R^N;HPLB<GJ[0WL[:D)**[NJ$@(K*VKJ*NMK:^IJVYM[BTIK +MFXORLJL+:WHK`[LJ:LK[:[N:"KH:HZLKZNKJ([NJNAI+RFN;RJKK2OI;X^HK +MNLL+ZZJ+ZZYKNZOJZONJ*@OC^XKJHBKKBIH26U,3ZZ(*(BLK:UM3JX*B(NMZ +MBK*Z,X,CPAJZ2R-+8_H::DLO+\MJHKK[2XKB&FN#:V)RXKNK6\M*RLO[:J+B +MRPMKNLI+VTO*FSLOJHH#BRMJZL(*DAH+.TKJ[PONFHL*,@*+\[\CRGJ3"OLJ +M*YMR&M*#,Z)RDGO3R^LC"[,ZLHIB>\H*N^JKVR/"J[M*&WJO2UIZ"QL"TDHC +M"YI2HR?K[DXSC_N:@LNJ<QIJ*B(KNK\JVNK;NWNSPAMNKOK+0YK"&[M[BDJ* +MFVL;>ZLK"HO;XIHS,GNRLJ.*8WMZZU,/:XJNFF/2(HZ:KY-J+B^ORF*KJZO+ +MJ_/#2UK:0T)RHJ*BBI/[^P,::@-J:NH[NMMK"V)*R^H+`L*#8VNR*@^Z.]NZ +M@SO"VCJZNAJ[*UL#>E)J>\(S6XKOJNORSJ*;C[OZHJKC[UI"^OLS2J(J>HL: +MBN]ZVBM+>VMC>Q*K:W/#+O+*ZF]#NA)+3RKJTAH[^I-K6DJ*BN)+:C)ZFZ^; +MBEHJBYL+ZNKKR_L*NV-ZBA(;"F(*:CNO&DK3ZGJJRAM#FML3.F+.PB^"LNL_ +M&YJ;2ONKZROJ`ZM:CK[:F^.CFUN+4U-J*Z)R2TLZ&EK;^\*R#QNBXWNJ<NJO +M`OXBFT.O:PIJRQL;ZYLK^NN:8@M"0J_[^@*J(ZHSVMH[NB*"2^*K;\.O[TLK +MXF)ZZGLBZJ-"8CHC`[KJ:UH*0[/;6LLJ"HM:PNL/VXH*#B*J*@/[XFLKZC,Z +M^B+#;[LZ+DK[#DK;BB_SFZXJ`XIJ:@O[&AM/ZIH+"EKBHF+JHLI[\V_+"SZJ +MNKJCJX/*:UJN&R_;:Q.#,BM;4JZ.6N^O8SOBKHHO\R/KZSK.SJN;FB[J1P^B +MBBX^^Z^+(\-:RF,;,\NR(J+#BS*R,IK[2PH[(O(*6X.3@[JB*F/O:P(Z>V.; +M:RH#@FI[JZ/:TJZJN[MSNUH23O(+ZGHJT^^#$RL[2H)ZRCLK6WL[:TLBRBH* +M*XL:"QN+>WH"J^/[VH)KPUMN^R,Z"H)Z>WMKLMHBTR."2@NJ>_/+^ZIB:G.3 +MZT*ZJ^O"FDNC^TIK+UMKHF)KJDNJPZ^;;EY.+JHK:V/3C[.S*^(R,CKN6NK; +M+_,*FK\O6RI.8LO;*C-+ZX\[.I*RDLX.PNN+*IO;,\,3$\N#(Z-#^I+2(CH: +MNGH**FNK.MHJN^N+<\\O2I(R`KIJR^OK"RJ[*TH+^_./#WO._NX".ONKNW./ +M+ZJBRAI":DHZ2BN[RVL*XHK[&\NZ*@OKZ^LZ8IIK6Y/#>_MK*\N*6B*:JNL* +M*TMZ.@N[(Z^3>RI:4G(">LK+X_MK"\OKZRL*^J)JFUM+"H+RRGM#`\M[6^.C +M*EK"R@J:JDOKFOH[VZKB@N*:2HHKNSNC$^]3(PJBFKJZ.LJ*JNN+JVJKZ\IZ +M.KI*RJH[&R.CVSM[^VI:XAK*ZHO[6YO[NPH"TC):JAM[:VO+VX-C6XO*RKHZ +MZNO+FYN[2B+B@J*Z*JIJ"HIJZ[M+2PLKBII*:QNC.PO+NQO;2VKZ>GK*"NHK +M"R,STP.+VO)".DM[RRIZXN(BHLHKNUM#,ULJLH[N&CL#LUNJ.LJ*>J*:NFH[ +MP]LJ^MH:JP,3`QM;XV,SLQO+ZIK"0MJ[+P^/TV/[2\OKNN)R;O[>7IYN`B)B +M8C(N[A(".LLC0W/3\R-[*[JJ,[_?'\^O+X]O#W\_4ROR_B;^:RGA`9EOZ.#` +MX,A&+D+>QJ8",W^_2IZF?BY*(U._AY>IUZ=:YL9^(\?7E^?;[GX.6MLOKQOZ +MLEK[D[MN!H8GX3$!Z4;@L("(DK_S)F@H_C_7ES-F**CFBG,OCW_G]_>?`@:6 +MIJ_7::FGZLZ^$@H;,_.CR\O[NTM+:Z*^!K9*>?%QH3L8L+#8AG._@M9H!H/W +MJ5^FB`@6KF^G)X>W-\?_6L;6QNOW"6E'^SXFCHM3TWOZVJN[>ULCXWO*;F9V +MAO=!T4%7*`#P8"BJGUNVB!8:9]?'8E:(UE(/)W_/_X=W!SMF5G82AVF)1XM> +MYJZ#/P^+KFZBP\_ONZ(B:ON+TF:^:3'1@=\X,'`@QC\'NZBXJ"('*<=2*,A6 +M`E^')]__IT<'&^;6-AHW">FG0L;&[J\G?]NNOG+;#P]#ZWI:(I*^9N[)<5$! +M/YAPD*`FI\>KZ/A6ZG=IMVYH..@NIT<'YZ?GQR=+)M86KL>):8=ZAL9.FW\? +ML[+^CNMO3Z\[>B+ZVBY>!C.!+5'9Y@!0\+@J-X=^N+CF'VGILU8XN#:CQ[<' +M9P>7U]_N%NCVFZE)J6^^QJ8*SW^3(IY>\M.GG]M"[C*J.Z*FAO\!K1'YED!0 +ML(CS=Z?F.,C^YVFI&Z@XR$8[)X>'1W>I%V\F*"B>)XF)Q_J&1DYC7Q]C4J:F +MDC-?IQ."#N[:*BM*;OY?@:V12:C`$,"H;W=_!CA(IE_IJ;NHN`@&&^<'AX=' +M%W>/7B@HGB=IB4<*AL;NDZ>?^VY>/GJO_R\J$FZRJR/;FMXF!T&M\2D(L!"` +M1N?7/T8X"$[G*7>BZ#@(AN/G!\<'MY?W[QY65CXGZ6G'JB9FKEL/;_NRCBX: +M6]-#J@*2(KO#N]+F?JDQK4'G^#"0(/['%]/6^&@NYZD';NA(*`YO)^=GA[<7 +MM\,FJ!:NAVGI)P*&AG*OIW_C,OZ^(F/O$SN**\LKNO(^!B;WL5&QEPA`<"!F +MW\>C%CB(#B>I-PK6""A>>\\?AS>75_>O7M:6;J>IUU]*?G[:,P]3ZW*.KCI[ +M8YN*FGHJ.PLZ+MYFJMG1T2$2('"PN`I'AV+HN':+1Q?_IFB(ENX#O^>WEU?7 +MYV(V5F8C]RDW4])^+NO3K^,*$@[N&IN#FXLK:TO*<DZFGN<!T3&)UH#P8!:3 +MQT^F"&B>T\>'"O;HUEYJ0R_?1U<IEZ_F*%9NYRDI9^N^'C+;K[.+HK+B.FL; +MN\JB6FH["R(>1F(9T5'ALN"0\#@J=S=**,A&.X='PP9H*&:Z<W.O'[<I:?>* +MEFB6BY=IEX\2WHZK<]-;NC("2@N;"QI:^DHJBB).YK+Y$:V!6Z!P<!@N!T<K +MEHC&:Q_G>P;H5E[*,R.#G_?I:3<:UFB6NU>)%X_"?HY*B^JZNHIKNVH:VEKB +M*C.OFZ).AB;7\:TQ%[@PD&!&#P<S9N@VZD\?.^8H5E[*0YLKTP<IB2E/YNCH +MWE_IZ0<C\JZB.AK"`DJ[VRO:,G+:ZV.SF_JNGF8J(:VM(0Y@D#"X<I__TG86 +M\F^/P[Z6UN;:BPHR"J>I"6EG<A8HQOLWJ;?/^RJKRM+^/H)C;],K`JXR"ILS +M\SOB#J;F[X&MD;D6`'#`*$J_,TY&9CLO6QHFMF8R"TI2[CO'Z0FIKX;HJ#Z_ +ME_<?D_-SHWH^9KZ;?Y]SFFZ.8FOC0P,[\N;&?[$M<6G(L)"`EOIS6J;F<A\_ +MNJ86=IY+P^+^OC-7R0F7HV;6MBZOIY\/_^>?2S[&9F(/IT^+[K[RRP.S&THR +M+OYFYW'M\1?X,'#@AH**$MY.:^>3GL:6AG+CNWYFSG]I26GGNB8&WA(;3__? +MA\</DH9&GCO_S^M"(KOS2Y(^S@H3,Y(&WW%MD=>8\)#@9M+N7J:B3_=3!E96 +MINM3*F;&<L=)2=</&@[>IMX28]]'=X?;_H8F<B,OH\KZ:_-ONZYN.J/[VMZV +MWY&-<>>@,+#8)H;6-@[/1[=Z**@F*A.K'A8&VU?)*6=O0\ON!C:>4[=7=]\J +M#K[N0DJ*>HKC[U,+8A*RZOOKPGX&HH&-K0G(P``@*-;(5L('EZ="Z"CN&UN. +MQD9^SQ?IU^?G!]_BEBB&8P<'/Y/#\YL"?MX2RP/C.POJ*@O+"ZO[>]J.!F*! +M;5%7N&#@6(C(&.@C*=?#)BA&^]."1G9^:Z='!P>WJ7=#)A9&,D,O<^]G!_^: +MIN:.ZQOJNDMO;VO2SF)SSSN.WJ;#P6TQ#SB8R/@X6*#VAVDG_L9F8J\:1E:F +M0Z]#+U_W*2D'FB;FSH+"&EM?=T>34OYNPAHB$N*CSR\[JBMK.TOZ;B8&CODM +MK8GV"!8(H&"`B/_I)QZF^J\O4I;6#J\;SEIG*>EW9X\K0IYFWG++KR?'IW-* +M;CZN2LH:Z[-3\_L*"GN#ND[^;IYF]]$M>1[V;E;@P`!(+W?SAM*'1S-F5K;R +M`X(F8D=I%R>G)X\*?F8F4BM+TX<WYR-"D@+"[@X:TS_O"_H[LPLN)IXB@B9. +MH>WQ'\:2NOA`0*#F4VLF+I<I+V;V_AJ2!C8:MZD'?T>IQXO^7KX.SFYK9Q>' +MTYO#6X(>)LYKKX,ZJE,3ZJ+R#G(2!G:WT:TI+G^IQD`P8.A>AO9.EXE_;I*# +M2N;V!F*_'U._*0G'ZEJ#2WZV9J+O?X]/YR?SHH+"CCXRBQM+JNO;^X+^3B*: +M_F8'<='I:D=I-D!`H.@HB%;:*2ESPE.GXG:VCB+Z2V]'*1<_\]\?X@8F>GLJ +M*E.GI^\[^QN:/GX:(\H.TN,/VZY."B_J!O9C87&Y8U=Y+^``F`CXH$A.AT?[ +M,Y>IH\9>2L*F_@M_!\<G)T>'6PZNR@+.DJ,/+_.3;^\K;N[JRS*.&CMJHJ+J +M6XNN'NX"S^'!*8?)2>;@F+CXH-@HOF\#"P?IMR(R4V/^AO(CDS/S3V<'#QO# +M<RKN$BH+RGJ;+Z^[>BL#&T(RN\OB,AKZ@L(:VEIB<JK)01DG*;DGN-A(^-@@ +M^)8"F]I?Z:E/2U\/TE[^(J+ZZEOGA_]3/U^S.CI+6\I"`KM#"O*K;R]K:DN; +M&KZ^$@+2(JO:HIK:_UGA-T>Y">Y(*(CX6*#(-JZ>LO<IQV^'-W,R#JZR+FZ2 +MPS]3CR?G#U./LUNKXH):XFY2*KMKRS/OHRHK*SJR,H(2DM*.CE*#^>'7E_DY +M0Z@V*+B@X'CHMM:>1U?'9ZGIIW.KNMK^ICYJRZ*C'^?_OZ=_#UM*(I(N3NY" +M,J*+0Q-S+U,#:F*"4M)NCM*RT@Z'(3EG"9DI3F9&"+B@(#@H*.B*Q^?G%PE7 +MAW_S`Z+>INXR?JZ##^^/9T>'_Q.3BR[>3J[>ID*#<Z.O_X][ZRL"4I)R;E*2 +MOJY;B9FWJ?G)G_YR]F@X()A("+C6`],OY^D)UW?'9Y\*;D[NIL8^HJO+CP?' +MQ^??G[,:#N[.YN9^+F(ZRZ]_[Z./3WHNJBH.'F[^#I?YAS>9.8<K<]ZH:-@8 +MN$B82(ZRLF_7Z5?IJ9=WGR/*VO[&II[^[HHOSZ=G9V>_4Z-K\GX^SDY.KGKJ +MJ[LSDTL[,QN*NKK"/OXC::FO5[GI$XM#3H:(.`B(N!@H'N:>HW=W]ZDIZ1?G +M?R\[/J9.?J:F(DM+,P\G)_^/#P^K\D("CM[.KN[2`NIKZU,/D[-#F_I23NNI +M]\-W":EC6^^.9N@(B(A(F"AF1B9K1P='*>EI5_=G?R^N/D[>!H:NTC*[+Y]_ +MIZ=?GX/+Z\I2'LX.3KY.DDJ+ZB.?3[.3\XM:$KHW]\.GJ:E[8@,RYJ@H*"CH +M2"@FIB9B)V?G]ZGIUS<GGT^:GIX.WH;^HJN[LS^G)W^_GP^;"LHBCH[N#K[N +M6IKZ.[,C6P-;Z_J"KF[JYV<OY]>7[[L#NKZVEM:HZ(BH!J:>$L^'9\<7*7=G +MIS\#8N[./KY^CMI[0U.?Y^=?_S]3.QKRK@Y./DYN+A)::NL;`R.CH_L*N@J" +MKBKG9Y/_M[>3:AN*CL8V-G86*/8>3H[";R<?IP?WAW\/\]N"#@YRHO+Z6R\/ +M[[]_/X]3DZ,KHO+R[HX.;I*RXIK+V^N+>SOKNKK*2J)"^JH3WS^/_V=?RPIK +M2KYFYF:&QL:FOA+"2G-/OV__)Y_OPS/CZKIJZRL+FQMSKY.3$_.[B@H*VD)R +M`GHZ(@)ZJBKZ&BN[*_IBZJM*8AKK2MH::P/O/X_/___O"ROJX@X>/I[>WGYN +M4F)ZZ\,S0[,3K\/;VULC.QMCXQL[&TL[HSN+"QO+:HN+*[J::FI*>GI*NII" +MVJKZPGJ+JF*:JLL+JXO+(YN+.]OCFWMCL[.C>\OJ2AHBLA)2KJ[20D+"VGIJ +MJ\M;`\-#0T/#LS/;&\N[R]L;"ZIJNXMJ"KKZFEJ::FJ*J[KKFXI*BRJZ"@HK +M"@HZ:JLKJZH[NROKRQN[BSLK*JNK:\LJJXJZZZH*JBHJ*NHJ:NN+2GIJBOJB +MHFO+JRI+`WLK"QM+BTMJR\LZ6JL;^XN+VWOJ"JJKR^KZ2NMJJBHKJOH:>KOK +M&KIJNDIKR^M[&WO[F_N+L_O*BOMK>IH**LIB@JN*RTJJFXNJ*_N[:@JJNF*: +M*JIKJJJ["PN+JWL[NDH+"PL+"YL[:^NKJ\MJ*@KJ&SJ:BNK*^NMJ"KN+&BHC +MJB+*(UO*:B/+JFH+BWHJ:VMJ*^LZ:PLKNDMCFL+:2JHJ:DO;VRMJRRO+Z_KJ +MJ_HJB[JJ&SK*>\O*ZW.*:CN[JOIJ(FI+RN-+Z\JJ&TJZ&IN*HNK*BRH[ZHNO +M`]N+&ZK*HO(*:AO*PJNKJJ)[@XO+NHM+R_K":OJ[NCJ[ZULJRZO[NSH+"[N* +M"DN*>[N+:DHK0EJ*:HMC:YJJRNN[NQM;>X*B:BJK.IN#([L+2^)ZN^KJ:VIZ +MJNOZBTO+JRMZXKH"JP-[J_N3R_JJ.YMZ"NH*BG)BBDN+:QN3XQMSBZ*N<EJ: +M`GK*2Z,C:^O#&SKJ:Y/OP\O:FIHB4HJJ>\.KJWL;2@*:XBJJ#H+#[^^#JZH; +M0J[ZDSLRRLIK"JJ[N_N;X]LK@ZONKCMJ$DJC8ZOC.]H:BRH".G,S(CJ;"PKJ +M2KHZRZ,+(LHS*KOC"VJ*"SJ*.DH#^[L*V[H"ZMJZVF.;VFO;XWJ+RTKKFV.[ +MBB(2&D(N@P^OBSL"CHKS>]IOTVMB[M+ZVPJ;K_,S0PIB#@ZN>HO+Z^/;6WMJ +M>RN[VOH+*BL+JKNC>OM[2BO;>J)+PII*2YJKVRH[&\NJJ[LJ:SIZ@\NJ.^IZ +MNVI:V@K+._JJBTKJ(RM:JR.CBB([ZRI+"^HC2PLZ*DL:^FOK2@N*PLKKRPJ* +MJNKZN^,B:\,+"K/;2KL+.LHJZBJ*NNK[&VJKRX):^ZK+2KJ:NPN*NGK+"[LJ +M>POJFS/["@,JBFJ"VAL;NBH+2FO*>@H:*L,[>CM*"FN:VZ^C*JJ*+F)*ZBJJ +M:AO#VCL+P^.RJNM;.\):JDMB*IM2:^.O*IHCRMMJNGJJ(ZL*XMLKKO.;,H*K +M8SJ[JZH;>QOZF\N:NVLK:\H*B@LKNGH[XSIZRXJRJUL:*J-+:B,[VHN*J@LJ +M:KHZ:BHBJ]-#:Z*;8PI*2M+Z2VJ[ZBOJ2[OK^[KK"VKZ:HNK"_JJZRJCF^.# +M([HBZMJJBZXNBMMJZH,CJ\NCZMKJ^BO+NKHJ2LM[ZHL+R^J+:AN;"YOKBTO* +M2O(RFN*RVJ.[*T.OB@JOPVO[Z[H*HS,B+KKK2EHJ,IK;F^)B\_OC2^KCBRIZ +MBDK*.BJ;B[.[*H-+.J*ZJ^H*@L+ZBFO[JHLK._,;JZ-CHOJKZM+ZTS,K*@MZ +MBYLJ,GI*ROO:&CMKRJK[2LL:FNL:*^H[FV,C"[,C*WMJBVH"8NMK:KO:6ONC +M:C*[H\M+.@KZJ\JK.LI;2ZNK&AH;6VKJ2UMC&XIK.[JZ@FKKNNKJ*@J**JN[ +M:\MKBZJZ^[NJJOHJ:YN[`NH+"IK+FRH;JPJ:2JHJ$R/BZH/3"O(B@AKJ:^H[ +M:SO[BXJZHZ.C:ZJ*2JJR6HNKB^JJZVH+*SIK&Y,[RFHJZZHJXCJ;N\IZ^GH+ +M.RLJ:@M+RDHZ&HMK>SL+FUN;ZJN*"BI*:@I*^R,KJGOK>NN*>KHK:MJJ^XJ: +M2SL*JB-[ZXL[Z^KK"@N[:XN:RHI*"NJ;JZIJ*KMZNJJK&KIK>FH[^TM+^RO[ +M6RLJ^NL[BVMJ.^O*R[I*2J*:"BM["RIJZ@KJRTIZ>_.+NCO+*XH+2WKJ*RM* +M:RH*NXLK>BI[BIJZZ]O[*PIK.[N+JKLJZJM+RYKZBJOK*\IZ:^NJZ^OKV@J+ +M>DH*:DN[:\N;VZH+VVNJZNI+.ZM*JVJB`CKJBJOKNZH[.WLC^FJ[&ROZ*VM* +MFFI**]L+NPMJ2LI+Z\KJ:IJ*.^J*JRHJ"TN**PLK*BO+2SNJ&_MKJCHJZRMJ +M*KK:R@(Z:VKJ*ULJ2Z,[6_I*NHKKNDHZFYO[B^HJ*MNK>JKJZSM+2DH+*\N+ +MJVKJ"RL;"XJJN^N:VMJ*2@IK^\OJ"^M+NN+K2RN*RYO+>VHZX@)JJNM**TOK +M&YNCVSOJ*J/+J_N[JNHJRAK*&HHJZGJ:BKKJ*ZIK.SN+F\.[JRHJBGJ*RHIJ +MJGL+*VKK^[N+:ZL;.AJK*@I:.LK+^VO*"X.+BWL+:O+RDG*:"ALOO[^_+QL* +M`JY^IAX.@@K+L^_O[^]#2VMJ"NHJFZ,SLV-;2[N:`M+2TJYN3KZ^[AHC$S/S +MO]\_<QO*(J+Z"HNST[]O\QL+2E(.3L[N;N[N,J):NNJ[TP^??X_O[V];ZQIB +M&N*"TCHJ*BNZZRO+*OI:\O(BFN+"FBI[6WM;D]-3TP-CL[/;BVHZNCIB\JXR +M@GJ:@LJ+VV-CVTMC([L+:CJZROK:.DIZ^OI*"BJKZWN;HYL;>\M[FYM+*RHJ +MZLIJJTJ:.@HJ"LI*BJKJJ^J*:JN;^ZNK*TLKZBLK*\N;BRN+ZRIKRZK+NZK* +MBJOJ:HK*RLJZ^KKJZ@HJJVO;(_MJ*\OKNSM[BPM+ZNJJJOH:>IHZ.DK*2JLK +M2SM+>_M[N[L+ZZOJ"@J*:FJK:RMKBRN*JFLKJDKZ:BHK*KI*RJJ+NQL[R\L+ +M*^IJ"FHJJJJJJ^LK:VLKZVLKJZJK*JJK:HKJBDJZNKIJJBLKB\N[.XOK:^NJ +MJPN+RSL[2PO+ZZHJ2CI*RDJZ"KIZRHJJ:^OKBTL+BRNKZXMK*NHK"_L;^VNK +M:^NJ*@JZ.DJZ2NH*"FHKB\M+*ZHK:VL+R^OK.SLKBLI*"HJ*"JHKJRNJ:JMK +M*ZHKZZJKJXK*"_O+NXNJJVLJZNNKJVN[RZLJJ@L+JCIZ2KJZRFJK:\M+NXOK +M:^NJ*JJKJRJ*BBL+:^MKZZIJ:@J*JZNJ*VOKJ^LKZJO+BZKJJBO+"^NJZNNK +MZ@H**JN*:NKJZJNKJNM+^SN+*FJJ*LI*J\O+N[M+:^OJ2LH*ZBKJ:NJJ*BKJ +MZNO+BVNK*JL+RPL+:^OKJFJJJXIJJNJJJXI*:FJ**JOJ:JNK*PMKZPM+R[N[ +M"PMKJHH*RNJK:FHK"^NJ*NJJ:@HJ*^MKZZMKRRIJJZOJJBNK:XMKBPOK:BKJ +M"FHJZNKJZBKKZZNK*RH*:BNKJRLK*PL[BRN+BXOKJJJKJJKJ"KJ**FKJZBJK +MJRNK*NJ**NN+BXO+2XOKJRHJ:POK:XN+2POJ"BJ*"BIJ"FJJZLH*ZJJKJ^N+ +MRTN+ZXL+*RHKJJJ+*\KJJ^HJ*RJK*XIJZZKJJZJKBRN*JVOJ*BMKZRNKJZOJ +M*JLK:^LJJNLK*BJ*"BIKZVO+:VN+*RHK*RJJJFJ**BHJZHIJZ\OK*PN[RXLK +M*^NKZDJ*BHJJ*BKK:VL+*RHKJXKJJNKJJ^J*JZOJJJLKBXLK*VNKZRL*"FOK +MJPM+J^O+ZRHJ:NJKZHJJ*ZLJZHHJJ@I*:BKJZBN+:XO+2\N+*RLK2[L+"PMK +M*HKJ:HJZNBKJBJLJBFJJ:BKKZVMK:XN+*ZJKJBJJ:TMKZRNK*JHJZNLKBJKK +M:FJJ*NKK:XN+JRHKJ^KJ:NHKBROKZRL+"^LK"\NKJNJZRFK*BJLKZ^NKJZLJ +MJ^NJJ^LKZ^NJ*FIJJJJ**NOK"VNKJ^NJ*VNK*VNJZJHJZBJJ*BMK*ROKJJLK +MZ@HJJ^HJJZNJ*^OKZVMKZVNKBBHKJHJJB^MKBVMKR^NJZRNKZZIJ*BMJJHN* +M*HNKJJMJ"JJKRNHJ:BOKJFO+"VOKJZHKJJOJZJJKJRMK:ZJJ*JIJ*JLJZBMK +MJJNKZBJKJJIKZVL+ZROKJRLKJFKJ*NKJZNJK*ZNJ*VN+"ZJJB\OKJBOKZVNJ +MJJLK:RLJ*JOK*RIJ"NJKZDK**BKJZHHJ*XMK:VN+BXMKZVO+"XN+"\N+Z@HJ +MZHJ*ZNJ*BNH*:FH*ZBLKJRN+BPL+RSL["\O+:ROJJRLKJNIJ*NJZ.@JZ2NKJ +M:JOKBPN+"\O+"\O+"^N+JPKJ:LH*:@H**ZMJJRNJ*VOKBRNK*RNJJVNKJXN+ +M*ZLKJJJJ*JNJ*JOJ*JIJ*HOK*JLK*VOJBBNKZXOKJFMKJJNJ:JNK*BHJBJJK +M"FJKJFL+*RO+"XOKJZNK*BJK*BKKZZHJ*RLK*ZJJ*BKK:VOK:JKK*FHJ:FJK +M*HKJJBJJ*HIJZ^MK"VNKZPOKZ^LK:PN+ZXN+JRNK:HJ**FKJ*^KJJ^OKJRLK +M*^LJ*BKJ:NJ*"FJK"VMJZ\LK*JNJZNKJZBJJ*^OK:^L+:ZOKB^OKZZHJZZOJ +MJNHJB^NJJRNK*JKJJZHKBZNKJRHKJZJKZVNKZJJJ*HJ*RNHJ:FIJ*JLJJXN+ +MJZK*"NNJ*JO+NTM[^PN[^\MK:ZNKJHH*RCK*R@H*:JHKJRLKJZKJRLJJJJKK +MR\M+N\L+"PN+:VNJJ^OJZBNK*NH*2LJ*B@J*BHJKB^LJ*VMK:TO+ZVOK:VLK +MZXMK*ZKJZNJ*:JNK*BHK:^LKJ^IJJRKJJVLKJBHJJFJJZ^LKZXL+ZRLKJZOK +M*ZNJ*BIJR@HK:ZL+NVNKBZJ**JKJJNN+"\MK:JMKJJHK*BJKZHKKZZLKJRJK +MZZKJ*HKJ*JLKJHKJZZNJ:^N+R^LJZJLJJBKJ*BKJZBHJ:JLK*NOKZ^N+ZRMK +MZVMK:VMKZRLJZHKJ:FJJJJMK:RMKJNJK*FHJJBHJZPN+:RLJ*JLKJFJJ*BIJ +MBHJJJZMKZ^MKRVOKZZJJ*RLJ*XNJJNLK*ZH*:JOJR@H*:BJJJNMK:[L["XL+ +M"VNKZNJJZLKJ*ROK*ZMK:ZJ*"NH*RHKJZNHJ*XOK:XMK*^OK*PN+*VN+*RLK +MZVOKJ^I*ZNLJBJKK*BJKZJKK:NHJ*JJJBNJK*JOK*TL["XL+ZVHJJ^JJBVOK +MZZIJZ@K*"HHJJBJKJVL+2SN[^SO+"^NKJBIJ"NIJJJLJJBNJJ^H*:NJ*BNJ* +M*NMKZ^OK:XMKJRLK*RNKZBHKJ^J*JNNKZVN+"XLKJZIJJRLJ*BN+Z^HK*ZJ+ +M:VJK:ZLJZBJK*RIJ*FIJJZNK:XMKJBIKJZHKJRJJJZHJ:JIK*ZKKBVL+"ZJK +MJNJ*BHIJJBNJZJHKJZOJ*JL+BRNKZTL+Z^OK:VLKJBJJ:BHKZ@H*BHKJ*BJK +MZ^NKJ^OKZBHK:VL+"XN[NVLK*^NJJJLJZJLJZJOJ:NIJRLJ**FJ*:JOK"VLK +MZ^LK*ZOJ*VLK:XOKJVMKJZNK:^LK*ZJJZ@IJJBLK*^OK*ZHJ:FJJ*FKJZBJK +MJVJJBXM+2PMKZVNK:HKJJFJJ*^MKZZNJ*RNK*NJJ*ZJJJNHJ*ZLJJZNK*RMJ +MZBMKJBJK:RLJJZOKZRNK*ZMKZ^NKZ^LKJNHJ*FIJ:HKJ*RKJJ^OKZZJK*ZNK +M:XLK*XL+ZROK:ZNKJZJK*RKJJJLJJBNKJZJJ*ZHJJRNJZNJJJNHKJZKK:\OK +MJ^NJJZJJ*BJJZFKJZBNK:JIKZRLKZVMK:VNK*BIJ:BJJJ^NKJZMK"XNK*NNK +M:HJ*:BJK*BN+ZVLKJZHJJBMK*ZKKZZJK*ROK"RNJ*RIJJBIJ:BHJJZNK*BJJ +MJ^MK*ZMKBZHKBZOK*^JJ*ZLJJZJKZZKJ*ZJ*:HH*ZJNK:PN+2[O+BTOKJJOJ +MJBNJ*JJJ*JJJJNJJ*VKJZVHZ:NH*ZBJ**PMKR\O+2SN[BPL+:ZJK*ZKJ"@IJ +MJJNJJBJJJBKJJZJKJRMKJRJJJZJJ*FJKZZKJ*HMKJZHKJJLJ:JHK*JLKJZOK +M:^OKJZNK:VLJJROJJBHJJRLKJJOK:RNK:RNJ*RIJJBNK*JNKJZNJJ^OK*RJJ +MJZOK:^JK*RKJJRKJJBJJ:HKJ*JIKZRLKBVL+*ROKJBOKJNL+ZRLKJRNJRJHJ +M^HJ+ZFHJZFKK*ZKK*^OKZRNK:XN+:VL+BRNK:@HJ*NHJJNJKJ^HJJRMK*FHJ +MJRJKZRMKJZHKZRN+:VMKZZJKZNIJ*JOKJZJKJFKJ*NN+J^MKZRLJ*BIJ*NIJ +MZJLK:VN+"VMKBXLKZJKKJHHJZJLK*JL+ZZLKJ^KJBLIJBFJK*RJKZXN+ZRN+ +M:RIJJJNJ*ZLK*ZJKJNHJJ^N+BVLK:FIKZBIK:RLK*^HJ*ZIJB@K*RLH*JNHK +MBVL+"VL+BVN+BXN+:^OKZZN+"ROJ*JKJ:@IJZNJ*:NJ*"FJ*JJNJZBOK:PL+ +MR\N+BXLJ:JJJ:JL+BROK:XMKZZNKJZLJ*NJJ*JHJ:BHKJBHJJBOKZZMK:RNK +M*FHJJZJJJJNK*ZLJJRNJJZJJ*BHKJZOKZVN+BVMKBZNJ*ZKJZHH*:NIJ:JKK +MZZLJ*ZHKZRLKJZOK:ZNJJ^N+BVOKZRNJJBKJBHIJZNIJJXOK*VMKJBHJJBJK +MJRMK:PL+RPL+"^LJZFH*BFIJ:BJJ:FHJJNKJ*JJK:ZNK:ZNJBXNK"RNJ:^LK +M:VLK:RLJJJKJJZLJ*NIJJJIJJNOK:XLKBPOKJJLJZJHJ:JJKJZHJZJNKJZLK +M*VMKJZMK:ROKZXL+:^OKJJNK:FHJ:HHJ*NKJBBJKJZLKZZHKJZN+ZROKZPN+ +MZVOK*ZNJJRHKJRKJZBJKJRHJJZNKJBHJ*NMKZVN+ZVMKJBJKJZLK*RNKJBHJ +M*JHJBFJ*"LI*"HKJ*JOKB[M+:TL+BVLK*BOKJRLKZXN+Z^OKJZHJ:FIJ:FKJ +MJJOKJZLK*ZOJZBJJ*ZNKJRHK*RJKZZLJ*ZIJJZHJJBOKBXLKZVOK*RLK*ZLK +M*ZHKZXL+*RMKJBJK*NJKJXIJZFIJ:FHJJZKJ*NHJ*ZOK:^OKJHJKRXOK:XN+ +M:^MK:^LKZ^H*BLJ*RDIJZJHK:^NKZRNJ*VL+N[N[^[OK*ZIJ"KK*2LJ+ZXKJ +MJVMK*FIJJ@NSRM[*4XL2ULYI9]I#:Q.?<\86*IG):#CVYTFSB(@+UP>+ZW+> +M#D[/YZ?G4L[:VN[>_HZ?M_?G#B8#I\M+2NZZ8OHR!I8NK[,/GR^CB_)J3Z,* +MJG,3V\/KJHM:KFZFOHL;XHOKVT\C&H,*8L^O"V)J0R,K>AK:2I+2R^\3JRZ^ +MRJ//CR/:[JJ*NSH:2QL#.CIKVJ+ZZNJ:VSOK"QNS8P/*BC-+VB[NLJ*K*BJ+ +MZBJC&YOKR^,C:K+K0[LK4AH+N_/Z2FOKBOJ*HLJ*J_/CFRKZ8OJ;FR):N]N; +M*CIZZZ_38FZKNXIK8BIC>\I:BPH;(ZL[JNJ*2N(B8WN[NPHZJJ-+"AHB"[.; +MJEH*^DK[FPHJBNNCXR/Z&NLJ:NK:&LM+6@J[BQO[F@(Z>ULJHIIJ^]N+"_K+ +M8^N:FBMZJTOJR^I[(\M+*OK*6X.K"OJZ"HL+.KJ*BHJ;(RJZNDKKNXNJRSO+ +M*AIJ2VLZ.BL+6QL*6OJ;P^M:PIJJB\N*"NNJHQN*NDN#R^M*FBN[ZHHJJVMJ +M:CKB^LI[JNLC:LO[6\M**JMJBHO[*HL+R^OJ2JJ*RFMJ2NJ+RRJJ"OH+2SNJ +M.FIJRFKKJXL[(TL*NHJ[*TI*^FM;&XLJ>NOKJ@NJ:OIK:ZHKZBH+:VLJBBHJ +MRAHZ*_O;"[LKJTLKJDJ:2NKKJBL+Z\N*JJNK2ZK*JVN*BJO*NFL+BZJ+2TNK +M*BIK2TMK*NOKZXKJ*KH*ZHJK:ZJ*JVN+ZRJB[M+B^BH+^]NCX^/C(Z/;FWN[ +M2PMK*ZLJZFJ*"@K*RLK*R@H*"@J*BFKJZBJJJJNKJRLK*^OKZ^OKZ^OKZRLK +M*RLK*RLK*RLKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNK________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M________________```````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +$```````` +` +end diff --git a/share/isdn/6.g711a.uu b/share/isdn/6.g711a.uu new file mode 100644 index 0000000..67d9945 --- /dev/null +++ b/share/isdn/6.g711a.uu @@ -0,0 +1,277 @@ +begin 644 6.g711a +MJZLK*ZLKJZNKZFIJZNIJZNHJJJJK*^MKBVMK*RLK*RNJJJNK*RNJJJHJZNHJ +M*BJJJJJJJZNKJROK*ZJKJJNJJZMJ:PM+N\L+:VNJJJLK*RMK:RNJJJHJZ@K* +M2DH*:NHJ*NL+RPMK*ZHJZVOK*RNJJROK:RLJZJKK*^H*BBHJJJKJZBHK:^MK +M:XN+B\O+RXLKZ\LK:@H*BFIJBNJJJJOK:^NJ:BJJ*FKJJVL+2POKJBMKBZIJ +MJBOKJBIJBNHJJJJJJRLK*RNKZBJJJ^MKZZNK*RLKJNKJZBHJJJLK*RLKJRNK +M*JNKJBLK*^OKJRHJJJJJJ^MKBVMKZ^LKJZLJ*FIJ:FKJZBJJJZLKZ^LKJZNJ +M*BHJJJNK*^OK"\N+:^NK*ZKJ*JHJ:HJ*BHJ*ZBKJ:BHKZVM+BXO+B^OK*ZNJ +MJROKZZNJJNIJBNHJ*BJ*"FJJJZJK:XOKZVMK:^MK:VMKZZNKJZLK:VLKJNJ* +M"@K*"FKJJBLKZVMKBVLKJRKJZNHK:XMKJRJK*NJJJRKJZNKJJJKK*^OKZ^LK +M:VMK:^MK:VOK*ROKZZOJ:HJ*"FKJJJJJ*RNK*NJJJZNJJJNKJ^OK:XMKZRLK +M*^LKJBHJJBKJ*JJJZNJJJ^HJ*RLKJRJK*ZJJJBMKBPN+:^OK*ZNKJBKJ*NKJ +MZNJJJJNKJBKJZBJK*ZHKZ^MKBVLK*^OKJRHJJRLKJRLKJZKJ:FKJJJJK*^OK +M*ZOKB^LJ*ZNKJNKJZJJK*RLKZ^LKJZHKJZNJ*NKJZNJJJZLKZVOK*ZLJ*BHJ +MZBJK*RLK*RMKBPL+BVLKJJJJ*HJ*:FKJ*JJJ*BJK*RNJJ^OK:RNK:PLKJJLK +M*RNK*ZNKJBIJ:BIJBHIJZJJKJJOKZROK:VOKZVOK*ZJJJRLKJZNJJJNKJBHJ +MJVOK*ZNJJJLK*RN+R\N+:^NKZFIJ:FJ*"HHJJBOJ"BHJ*JJJJBMKZVN+R\O+ +M"VOKZ^OK*RLK*ZOJBHJ*B@H*BFKJZJJK*RLK*RNKJJLKZ^OK:XN+BXN+"XL+ +MZZNJJBIJ:@H*BHIJBNJJ*RLK:TL["PN+*ZIJBFJ*:NJK:PN+:VOK*ZHJ:HJ* +MBFHJJ^LK:XN+"XMKZZNJZFIJB@J*ZJHJ*JJJ*RLKJZOK*ZNJJJLKZROKBXN+ +M:^OKZ^NJ*BJKBLIJZBJKJJJJJZNKJZLK*RLKZ^OK:VOKZ^LK*^LKJJHJ*FJ* +M"HKJZNKJJJNK*RMK:^LKZRNJ*NKJ*JJK*RLK*ZLK*RNKJJJKJZLK*RLKJZMK +MBZJK*ZNJ*BHKJZJJ*BHJ*NKJJJNKJROKZVOKZRNK*NHJZBHJJBLK*^NKJBKJ +MZBJK*ZNKZ^NKJZLKZXOK*ZNKJBJJJBHJ*BOK*^OKZ^LKJVKJZ^OK:^LKJROK +M*RNKJBHJ*FKJZJJJJZHJ*BHJJRMKB^OK*VMK:^MKBVLK*ZKJZNKJ*JJJ*BKJ +MBHJ*BNJJJZLK*RMKR\N+:^OKZZNJ*JJK*RLJ*JNJJZLJ*FKJJJHKJZLKJJHJ +MJBMKBXMKZVOK*^NKJJLJ*JJKJJJJJJJJ*BKJ*BHJJJLKZ^OKJZLK:VOK:VMK +M*ZJJ*NIJ:NIJ:BJJJZIJ*BNJ*VMK:RLKJZJKJ^OK*RLKZRLK*ZNJ*BIJBHJ* +MBNJJJZLK*^OKZXO+RVLKZVLK*ZNKJZHJBFIJZBKJ*BKJZBHJJJOKZ^OK*ROK +MZ^NKJXN+*XN+:ZLJ:FJ*BHIJ:BJJJBNKJRNK*^MKZZLJJBN+R\L+BVLKJNKJ +M*JJJ*NJ*BFHJJZOKZVOKZVOKZ^MKB^NK*^OK*^LKJRJJJZNKJZKJ.KH*"BJK +M*VOKZRLK*RLK*ZNKJBHJJBOKZ^LKJZLJJBHJJJJKJBJJJBJK*RLK*RLK*RNK +MJZNKJRLK*RLK*ZNKJROKZVMKZZHJ*BHJ*JJKJJIKZRJJ*NHJ*BHJJJNKJZNK +MJZLK*RLK*RNKJRIJ"HJ*:BHJJJJKZVN+"XL+BVOKZRNJZNKJJJNK*ZNKJZJK +M*RLK*ZLJZNIJZJHKZ^MKBVMKZRJK:ZLK*ZNJ*JNK*^LKZRNKJBHJZFIJZBKJ +M*NKJZBJJJJNKJ^OK:VMKBVN+BVOKJFJ*"@J*:BJKJJKJZJHJJROK:^OKBPL+ +M"XMK:XOKJBKJJ^H*:HIJ*JJK*ZJKJZJJJZJJJJNKJ^MK:XMK:VOKJVJ*"HKJ +MZFIJZNHJ*JOKB\M+2XLK*ROKZRLKJZNKJZNK*NHJ*BHJ*JJK*ZJJJJJJ*ZOJ +MJBNK*^NKJJJJJJJJJZLK*ROKZ^OK*^OKZRNK*ZNJ*NIJ:HIJZNHJJJJK*RLK +MZ^OK*RLK*RLK*ZJKJZJKJJJJJZNJZFJ*:NHJ*JLK:VMK"SO+R\N+BVLKJBHJ +MJJHJJJNJ*NIJBFIJ:NKJZNJJJ^N+"PN+BXMKZRNKJZKJ:HIJ*JJJJJNK*JJK +MJRLK*RNK*ZNKJZJJJJHK*RLKZ^MKBXLKZNKJZBHJZNKJ*JHK*^MK:^NKJJJJ +MJRLK*ROK:VOK*ZNJZNHJJJHJ*BKJ*JNJJRLKZ^OKJZLKZ^OK*ZHJ*BJJJZLK +MZVOK*ZKJZHJ*BHJ*BJIKZVN+BXMKZRNKJ^MK:^LKJZLK*ZNKJZNJ*JJJJJNK +MJBHJZNKJZBJJ*^OK:XMK:VOK*ZNK*RNKJZHKZ^MK:^NKZNIJ:@J*ZBJJ*ROK +M:^OKJ^KKZROKZRNJZNIJ:NKJJBLKZ^OKZRLKJZKJ:FKJ*JLKZ^N+BVOKZRNK +MJJJJJJNKJJNKJZNJJZLKJZNK*BJKJZHK:VN+ZRLKJRLK*RNKJFJJ*ZJK*ZLK +M*ZHJZNJ*"HIJZBJJJJLKZVL+"XL+:^NKJBIJZNJJJROK:^NKZNHJZBJJJVN+ +MZRLK*ZOJZBKJJJLKZXN+ZROK*ZNK*ZHJ*BJJZRJ**^LJJJNJ*NHJ*NJJ*VMK +M:XN+BPN+*RJJJVI*:JMKJNHK*ZLJRHJKJBJJ:VOKBXL+:XMK:PN+JVHJJRIJ +MJNOJ2HKJJBNKJBJKJ^HJJRNJZ\N+BVNK*^OKZRNJ:@H*BLJ*JBNKJJNJJ^N+ +M"^MK*ZOKBZNJZZJJZ^OKZROJ*NJ*RHHJ:FJK*ZJJ*BKKZXM+B^NKZPOKJ@L+ +MR[N[BZOJZNK*2FK*RFKJ*BIJ:JJK*RJJJRHJ:VNJJRN+ZXM+ZXMK"XLJJXOK +MJHKJ*@H**JN*"BHKJBIKZPL+B^NJJJNK*RLK*ZOKJZKKZZHKJJJK:ZH*"NKK +MZFJJ*ZLKZVL+:ZOKJ^JKJNHJZXOKJ^NKJRJKZRLKZJNKJROJJJKJZBKKJNOK +MZZNK:XOJJNNKZJHKJBHJ*RHKJ^JK*^JJZFJ*JVLKRZHJ:JOKJFL+ZXO+R^NK +MZZOJZBOK:XL*2BOK*ZNJJ^H*BDHJZRHJ*PO+:^LK"RLKJXIJB@KJZFHJZVMK +M*ZIKBRLJBFHJ*ZHKB^N+RXNK"XLKJZNKJZOJB@KJB@HJ"HKKJBOKJXOKBTOK +MZPO+*NJ+:^LJ:XL**NHJZBHJRBKJ"NHJ:JHJJBL+.[OK:XLKBFIKZRLJJNK+ +MNZO+"ZNK.KK**FHZ*BM*:NJJ2POK2\L+JRJ+:NLKJNMKJ@HJBRLKZJHKJ^JJ +M*XHJJZNJ*FN+:TL+*ZN+ZZOKJZMKBZK**FIJBKIZ*DKJJFN;ZDN+BRJZZJLK +MZ^L+NSLKBXLJNRNJZ[KJBNJJ2DJZZ_J*BXIK"XH+*[LKJ^N+:XN;"ZOK^^LZ +M"NIJRJMKJLMJBLIJJJI+JDIJBDLJ2BI+:ZMKRZM*:CN[Z\O[:^I*ZNJJZJKK +M*LMJZFN+JTK**NHJZ^JJRSJ+*^MK:YLKRDIJ:[LKRKNK:BHZ:ZL*RFI+*RJJ +M"_LKZSLKBJJK^TM*.LNJRBJ:^VL::BI+*KH+JDO*NF.+BBN[ZZNKRNMJ"WO* +MZWHJRXI+ZXIZ:\O**RJ*J[OJJSN+&BJK&VNJBPJK^HJ[^[MJZWN;Z^)K.RIZ +M"GLJ.KJZ*ZJKJNHJ:PH*RINK:FMK(XNJRVN["RHKRNNB&HIJ8\HJPPL+RN+K +M*\KJFNNK"TOKJXOKZOO[J\JKZ_H[6GHKBRKZ*ZL[J[H+:PL;RTO*.TMJBTL* +M.BHJJ^N*BXOKRQIJ^CHB.LMK^^H[X\OJJFL[JEIZ:RN+:ZO+*\H[RBIKF\NZ +MBJK*NJJJR\MK*ZMZ"NOJRBL+JCNK*X/CN[IJ"CHZ2LLJBVNJBZI:*LN+NWJ" +MN\MZJBJK*EO[*DHJ^WHZ0SLZVWN;2XLK.[NJPNJ:4NMZ8ALJ`KO+NANSJWMC +MN[I#ZT)JJMKZ\AI+JN.;`QMZ:^."&JNZ>FO[^MJ*BJKSTP.S.RZ*BW*N>[/S +M$]HR>AIJ6O+*HS.[2YN:RAO["@H:2NH+2HJO^[I[&RHCJQJ[RRH:`FJZ8@JK +MZNJ**[M;F_KZPR-JZNNJBBK+Z_J*B[O+BTJ+6R(ZX\O::FNJRHJ:*QNK:RNZ +M2RLJJFJ**_N+B\IJ:X+B2ZJKVP.;VUL;BP+R2KOBZJM+NPO*8NJKNNOK6GJZ +M:HK+JTL*>Z-;B[NC8X/CP^]C*FHKZYHBFHJBXIHZ6B+26@HZHJK+"J(B,L+2 +MSHXBVN(K+Q_GAT?WE_<W=S<'7X]K4J8V*&B(R`CH*!;&)GX.KB)[(PL[8^,3 +M'S=I^5FQ4<%9X=G?1KA@P$#0K,"@&.@K=SDA(2&!H:GSHO9XX&#@6/@('N?7 +MJ<EY.2D'7S>!$8EGP<$'7L:(N!C04*!X8*#:R?EIB5E9AV:V;A:@($CH2/@H +MV\<OVY<A$2VMT:VM`>>VN&`0;(PL<$!@EI?9(8&148$7[Z((`/!`8.#@2#OW +MA[<YH?F7Y\?A;4$[8:TYAE;H.-B0[,!HH,`6B8D)H>$AF3]&GH8@`)C(&!B( +MY@\?:\<YB?>A+6TQ09&Q"::8(&`0;"Q`8&"X+[E96>$Q06EK:SYX``"@F-AX +M!O^?`T?)B4=/ORG!T0$A<7'Y0Z8H&$"LK+"`P.#^%REIH4&QV0<'!]9@8%C@ +M`."(SLH*9[GY*7<I:2%1D2'!<2$OQFB@0-`L$("`8);W"0D9@;&!R5]?.GB` +M(*!@8/BV.H//*?E)5Y>7GQ=!L?DA,6&IBV:(6$!0D(``P+A[1Q=)(0$!6=<7 +M9RC@("!`0"`()NO/Z:'9R;GYMSHO(7%I'\%!J6;&G@B`D/#86+"@6U>?9UG! +M@<G'5Z=HX*"88,#8-L)[I[FA.6F)E_I.]QG9V1F!P4D3(N[(0/#`P+!`&.;[ +MSQ=9@6%92:D?QGC86&``V%9>B@?)F7FYR:D/#D8J66&G:1%!=^.WD[A@0,!@ +M,'"@WK[&AR%AH1D9^3<F:*@X`(!(*&CF_Q>I*6D)Z1\;3ZD9X=D908&GZN]& +MX,"`0#!`@)A&\MNIH>$A(7GI)]*H2'B@('B(J%ZCI_?IB8GI%V=?)VEAX2EY +MP;D";LOH8&!@`,"`H`B&#CLIV=GY^9GI0XXF5GC8N`@(J,YCG[<IB0EIJ7<' +M)ZDAV5\)X5>F_B^H(%AXH(`@>(B6!JZ'B0GIN7FIWV\;)BBHJ&B(EIZNR@^W +MU]>IJ=<WAP<)&1>'.>F[#F.22$CH2*!82$C(J.;"0X?7J2DI5P=_[\K^9H:V +M=H8.PFJ_1S>7J:EWQX</FVH;+VLRVR^J3IH;3H:F_D96MN9F!GY:"FH;;V_S +M\^\S.UO#V_L#DQ.O;X_O[Y.#XQOK2LH*6N):>GI**JJK:XOK"KJZVH*BFF(" +MFKK:&FJJ2LKK2PM+&Z-;&_N[N[OKJJOK*ZKJZBNJR@IK"RL+6V-;FQO[BRMJ +MRKKZVJ)Z>J):2FJ*BNM+"PN[^\LKZVOKJFJKRVMJJVOJNDJ*B@HJ"SL[>SL[ +MNXLKJZJ*"NKJ"HJK:ZNJBPOKJBHJZFH*"NJK*^N+2[N[.TMKJ^H*NOIZ^DIJ +MJRMKRPNK*JKJRHJJZ^N+2SN[._N[.[MK*RNJ:DK*"DJZ2FIJZJJKJJLK*NHJ +MZHIJJBN+2SO[^_N[RVNK*HI*.KH*ZBJJ:\N+ZXN+:^LKJJKJ:NJKZRHJJ^LK +MZHJ*RCJZZNLKJLN[RXN+BVNJBHIJBLJ**JJKJ^O+N[L[>YO[R\O+BZMJ:NJ* +MNOI*RDHZ.LK*NLKJJ^L+._M[^[N[RVLKJZNJ*NIJZNJJ*RLKZXOKJZNKBHJJ +M:FHJJZNJJZNKZVNKJBHJ:HJ*"HKJ*JJJ*ZLK:XL+BXMK:XN+ZZOK:ZNJJRNJ +MZBHJZBKJZBHKJRJJJNKJZNKJZJHKZROK*^LKZRNKJBL+RVN+:VMK*NKJZNHJ +MZFKJJNIJ*JNK*VMK*RJKJZHJJJHJJRLKZPO+RXMKZ^LK*NHJ*NIJ*JHJZBHJ +M:FKJJBJJJROKZ^OK:VOKZXL+"XL+"RKJ*FIJ:FIJ:FH*"FJJ*JOK:VN+:VL+ +MR\N+:ROJ"@J*BFHJJZJKJZNKJJNJJJJJJJJKJZHKZVL+RPMKZ^NKZBHJZNIJ +MZJJJJZOKZ^NKJZJJ:^NKJRHJJJJJJRMKBPMKJZNJZBHJZBJKZZNK*ZNJ*BKJ +MZBJJJJNKJZLKZVMKB\N+ZRLK*ZLJZFHJ*NHJJJHJ*BKJZBKJ*JJJJBMKBVL+ +M"^LJ*XOK:XMK:RNKJBHJ*FH*"LJ*ZNHJJRLKJRLKJBJJJJJJ*ROKZ^MKBVLK +MJZNKJZJKJBHJ*BJJJRLK*RLKJZNKJZJJ*BJK*ZNK*RNKJZLJJFLKJBNJJBLK +MJZNKJRMK:VOK*ZNKJRKJ:NKJJJJKZ^MK*ZNKJBHJJBNKJRLKJRJJZBJJJJMK +MBRLK*RLKZVO+@X^3FC[>#N(JJ^HJRR-#8YL+:[O[Z^KJJJIJ*LN["ZOK"PN+ +MZZHJ*FJ*B@J*BLKZFBK/1R=:QC:^N]L"/L[*CS\SRSNO3R_;ZZMK>J)BVKJ: +MBBIJZDN;N[N+^PMJBNIKJAKZ*RL:FNHKZ\H*BLI+"SM+R^,CZOH[6QI::BNJ +M*@KJJAJZ"ZNK*ZO#RXOK>\OK>\KKZZHJHIIKRKJJ:@NZ2MLK:_I+XPOZ^F,[ +M*LK+XPLZ"NL;*P)J*\JZVFHZJNLZ:SN+2\LK*KN+J[I+^XNJ*]N;*F(KVSH: +M*DJKBVKZ2FLJ>FK+6[NK:\NKRPMKZDL;ZXK:"JMJ>CJJ2XH*2KO[N@N+*BOK +M.VIZBTN+"HJ+"_J*2RIK:VL+BZHJBPK:BHJK*XN[ZVNKRLN+BBLKZRIK*FJK +M2NLKB@NJ2^J*J[HKJXN+ZDO+ZVNJ2NJK2LLK:HNJZBJJZBOK*FJKZPNJ*JL+ +MZXMKJZO+B[H**VK**BH+"\LKBNOJ"^KZJ\K*Z^IKJVL+J^MKN^OJZNM*:FNJ +MBZMK^RKKBFLK*RN*ZZNJ:^N*"JJ+JGNJ:NNJ"TK*JNH*N@IKJNJKZ[NZN_O+ +M.ZNJR_LK"JHKZGJJNZJJZXLK*VHJBJHJ^FJ*:XMJ:ZH+JRH*B@N["RN+:\IK +MRRHJ:BH+ZBJ[:RH*JON+NIHKZWJZRJL+:QM[2SMJ"PKZ*HIJJNL+ZBJKJVNK +MR_KJ"RJK2NMKJFNJ2XHJ*XI*BOL+.PLKRXLJ^KKK:\I*"JN+2RMJBXLJRLOK +M*VKK2VOK:XLJJ^NZ:BOZ*PHJZRHK"NL+2_H*&[LJZCNK*BJK*HLJB@N+JLJK +M*JMKZNJKZRMKJVHJJ^HJ:HH+"ZH*:XMJ:ZJ+BRL*JFN[Z\J+Z[I+2ZIJ:RNK +M:@HJ"JHKJPL+RBMKJJO+*\J+ZXKJNGO**JKKNVK*BKM+JVJJJRN+Z@I+:XMJ +MRJKKR\OKJ@OK"FIK*OJK:CH+Z^J*R^HKNZNJ"SNK*NKK>ZN*"HHK*BOKBZN+ +M:PH*BFMKJNIKZVJZZ\MJBVOJ"JH+ZHHKBFN+BFJJ"ZMKJNH+ZRN+JRK**LJJ +M*\LJ2BHK*XIJBVOK:VO[*ZNJ*RNJ*ZJKJRKJ*@OZJFN*JFLKRLIK:RN+N\NK +M:VL:ZBI*RLO+JLMK:FL[.VJ*RVN+BOJZ2BHJRBOKJTIKJBL[RTM+JTKK:VNK +MZZHKZ^MK2JNJBJH*JJJK2[KZBHLJBXNJ:JLKJZHJBXO[:^M+.ZLJJRJK:ZNK +MZRJK*BJ*NJOJ^AIJR^MKJXM+ZXOJ*VL+JFMKJ@L[2DIKBNIJ:JH**JJ*"LN+ +MZJNK:RIK*PN+2XLJ"@KJJJNJJ@MJ:HJJBDJJ^PO*:FM[ZNM+"\N+BRO**@KK +MZZH*BV/+FGKKB_HZRFKK"BH+ZZMJ>^LJBZNKBRKZJDN+*RIKNTN[ZFLJ:FI* +M2CK**\LKJZL+ZXLKRBMKBNOK*FN+ZVJ**LM+BDJ+Z^M*:BL+R\IK:BHJJPI* +MB^O+JBN+RPLJ"VO+*NNK"JLJJDIJZLOJ"CN+:ZIKZ^NKNBMJ2JJK*HKK"[O+ +M*NIKJ\JZBBHJZZKK:RMKBNLK"[OKJFJKZRIJJNLK2WN[RBL+>JHJ^KH*:ZKJ +MBHO+*FLJ.\NK"JN;B^JJZVNK"LJKZRH*JXLK*JL*^NH+"RMKBVOK2LIJ*RHJ +MZJJJ*BIJRRH+2RNJBWNKJ^MK"RJ+JFHKJTIJJ_IJN@IJ:FNJJXN+ZXO[B^O+ +MZRI*RVJZ:JH+JNMK:\N+ZBN+2VIJZZOJRLJJJZO*ZLL+R^LK*EM+BKHJBOI* +MJNL+"[L+:PK:FAJ:8J)*ZBJJ.]MC0X-CH\-C&^LKJHJJROIZ:JL*BEIZ^DI* +MFCKZ:HIJJRJ+BTN;>]O;6YM[>TMKJ^J*R@I*.LIJZNJJZFKJ:HJ*"LHJJBKK +M"\L[NTL+2\O+"PL+"^LJBFH*R@KJ:NJJ*ZIJZBKJJJHJJJJK*^N+BPN+ZRIJ +M*JLKZXN+:ZNJZNKJZJOKZXMKJRKJZBJKJBKK:RNKZXL+:ZJJJNJ*"@K*BFKJ +MJJNKJVMKZ^N+:ZHK:^OK:PMKZROJ:BKJ*JHJZBHJ*JOKJRHJZBHJJXL+BVMK +MZ^MKZROK:RNKJNHJ*NHJJBMKB^LJ:FJ*RLH*RHHJJRMKB\O+"PL[^[M+BZLJ +MZHI*RFKJZBIJZJKJ:@H*ZBNKJBNKJFMKZ\L[^YN;NXL+*RJJ:@IJJNIJ:HIJ +M*FH*ZJLJJZOJ:BJJJ^LKZ[L[RVN+"VNK*BHJBHIJ"FJJJ^HJ*HJ**JMKBVN+ +MRPMKB^NKJRLJ*JLKJZNK*NJJ*HIJJJNJJJJKZROK*ZHK"PNKJBKJ*BKJJFO+ +M.\NK*XNKBFIJBBHKJZLK*^H*RLJ*:BJKZPO+"[N[BZMK:RLK*@IJJFJ*:HJ* +MZFIJ*VNK*^NK*VLK*XOKZPL+ZVLK*JJJR@JJ*NKKBVL+"VLK*DI*B@K*"LJ* +MZXMKRTMK"[O+B\N+:^MJNLJ*"LHJ*XL+JZM+:^KJ:FJK*FIJZJMKJRJKJ^JJ +MJJLKZROK*RHJ*ZLJJXN+:RLK"\MKJZJ*R@JZ2BJK*HL[NSO[RPM+BZJJJNJJ +M"GI*2GHZZBJJ2[MKZZLJJVH*:NHJ*^NK:TN+BTN+:\MK*RNKZBHJBJLK:BHK +M:NJJRLIJZFHKB^MK2VLKBVLK:PMK:XLKJNJ*B@I*RBHJ*JHKZ^OK:XMKJNIJ +M*FLKJXN+:RLK*RLJ*JLJJ^N+:ZLJ:@I*2DI*:JNKBTMKBPLKJVOKZPL+*VNK +M:JMKJBJJZNJK*FJJJHJJ*FKJZFJK*RKK2VLK"\MKB^NK*^OJ2NJKZPN+*XL+ +M*ZJKZ@KJBKJ**BKKZRJK:ZKJJZNKJZHKZZNKZ^LK:^NK:RLJ*JJK:VOKZ^LK +M*ZKJJJIJBLH**BKJ*BNK:SM+:XM+"RNJJPO+*ZJK:XNJZBHJBKJZ"LJ*ZBIJ +M*NN+Z^N+BXN+"XN+:RLJ:BJJJBKJZFIJ*BKJJXOK*^LKJNOKJRHJJJNK:TM+ +MRVN+"VNKJJKJ"LJ*ZBKJ*BJKJ^OK*^OKZZNJ*JJKJNKJJBNK*ZNJ*^NKZXOK +MZVNKJJJK*JJJJBNK:HHJ*BIJZJOKZRLK*PL+:ZNKZROKZRNKJROKJZKK*ZJJ +M:@IJBKH*JZJJZZNJBXNJZJJJ*RNJ*ZLK"PN+:VMK:^LK*VNKJJNKZNHJ"FJK +M*BHKJNHJZNKJJJKKZZHK"RNKBPNKJHN+:XMK*ZOJBFKJ*NHJJJLKJ@J*JBKJ +M*RNKJBNKJJKKBVLK:VMK:XOKBVNJZNH*2@KJ*BHJ:XLK*XMKJJJKJZNK*^LK +M*RNKJZKK:ZLKZZKJJFJ*:FJ*:BJJJRJK*ROKBXMKRPOKBVNJJZLKZRNK*RKJ +MZHJ**NKJJZNJ*ZKJJJHJ*VOKZVLK:VLK*VLKJBIJ:BKJZJJKJNIJJBNJ*BHK +MZZOKRXMKBXL+:ROKZRK*BFJ*:BIJBNHJ*ZNJ:VNJJRLKZ^LKJZNK*ZLK:\MK +MZXL+J^IJ"KK*BNJJJZLK*^NK*JHJ*JMJBBHJJBLKJNL+RSN[BTO[RVMKZRN+ +MJHKJ"DH*B@IJ:BHK*NJKJZJ+:^JJJVHJZRLK:^MKB^OK*RLKJJJJ*^NKJ^H* +M:FIJ*JJJ*RNJ*VNKZXOK*^LJZBNJJVLK*BOKJBNKJBLK*^NJJXMK*^OK*XN+ +M:@HJZFJ*2HIJ"LKJZJLKZXN+:VN+BVN+"VOKZRNJ*BJJJBIJ:FKJ*NJ*:JJJ +MZNKJ*XN+:XO+"POKJZHKJBHJJJJKJJJK*^OKJZOK*ZHJ:HHKZVJKBROK*^HJ +MJRKJJZHJJZJJ*RNJJRKJ*VMKBRLK:VLK:ZNK*RJ*ZFH*BFKJ*JLKZZLK:^NK +MJZJJ*VOKZTN[2\N+Z^OKZRNJ*FH*"@H*"DJ**JJKZXMK*ROKBTL+ZPN+*^LK +M*JHKZNHJ*NJ*RHJ*:NJKJBMKZVN+Z^OK*ZJ*BHKJBFKJJZOK"TL+:VOKZ^OK +MJNIJ:FHJJFO+R\O+:VN+2[LKJZIJRLI*2HJKJJHKZXN+ZZJ*:NIJ"FHJJNHJ +M"XLKZPOKZXNKJVOK*ROKJBHJJJIJ*NNJJZKJ*JJJJRNJJVLKJ^LKJ^LK*JJK +M*^KJ*ZMJJFNJ*XMK*^LK:VNKZVLJJJOJ:NKJJBNKJRNKJBHJ*NIJBHIJZJKK +M:TO+BXMKZ^LKZRNJ*BHJ*NHJJBMKB^LKJBIJBNKJZJJJ*XMKJJNJJFLKJFN+ +MZVOK*^OKJ^OKJBJJ*JJJJZNKJZNKJZJK*JJJZBJJ*NJJ*BHJ*JKKJZHJ*JJK +MJNN+:\M+B^LKJZJJ*JJK*RJJJJNJJ^OK*ZLKZRLJBFJJ:NHJJFMK*^NKJBJK +MZXL+Z^OK*BIJBFHJJZHJZNHJJBOKZ^MK:RLJZBHJJZNK:^NK*ZNK*ROK*ZHJ +M*JOJZJJJ*ZLKZ^NJ*BHJJJJJ*^N+JRJKZFHJJJJK*^OKZRNKJ^OK:^LK*^NK +MJJOK:RLKZRLKJZHJJBKJZFIJ:FHJZJMKBXMKJROKJBJKJJKK*ZMK"VMKJZHJ +M:@K*BFIJZBJ+:ZHKBVN+BVMKBPL+:VN+:RNK*BHJZHJ*RLK*BFJ*BHIJJBNK +MJ^N+"PMKZ^MKBXMK:RMK:^MK*ROKJRHJZDJ*ZHIJ*NHJJRHJJRNKJJHJJROK +MRXOK"^LJ*JHJ*JHJJJLK*VNKJNNKJZNJJJNKJJLK:PN+*^NKJHH*BFJ*BFKJ +MZJJKZRLKZ^N+BXMK:VLKZ^OK*^LK*RLKJRNKJZJKJRIJBDHZ:JLJ*VLKZVNK +MJ^LKZVMK*^MK*^MKZ^LKJJIJ:HIJZFKJZFKJZNHJ*RLKZVMKZPL+:VL+ZZLJ +MZNKJZBJJJBHJ*JNJJJJJJJLK*VOK:XOKB[L+:XNKZHH*RDH*BFHJJJNJJBOK +M*ZNKJRLKZRLKZ^MK*ZJKZ^MKZZHJJJJJ*NHJJJJJJJNJJJJJ*ZNJJRJJJBJJ +MJZHJJRNKJBLKJ^N+BPOKJBMK*RNJZJHJZNHJ*BJK*ZLJZFHJJJJKJJJJJBMK +MZ^MKBXL+"XOK*ZJJZBJJZJHJZNHJJJJJ*BHJJBHJJJLK*VN+:PO+BVMK:ZLJ +M*NIJ:BHKJZLKZRNJJZNKJNHJJJJJJBOKZ^NKJZHKZRLK*RNKJZLJ*JJJJBKJ +MZBHJ*NHJ*^OKBVOK*ZLJZNKJ*NHJJJJK*RLKZXOK*ZNJ*NHJ*JJKJNHK*RMK +M:VL+"XMK:VMKZRLK*RLKJZNKJZNJ*NKJB@I*"HIJZJHK:XN+:^OK*RNKJRNK +MJRNKJROK*^LK*RNK*BKJBFIJZBJJ*RLK*^OK*RMKR^OKZZKJZBHJJJNKJ^MK +M:XMKZ^LKJRKJB@KJZHH*"NJK*JHK:PL+B[N[BZOKJXH*"BJKJXO+:VNKZ^NJ +MZ@J*"JK*>HHKR[M[2XNJ*_-3#GY_R^C(CPE;2W^7-ZLV:!('B:DFH,A)&<Y( +M'H?;`F(OWW8HMC>9"3>HJ!XZ\BBH<JFYB>?N[D/C.@+NNY/NYJY"YC[:BY]' +MYRHF9J)?`^+:^R>_D\IC_Y/NEN:>8U.2_FM'7PL^.VK[_ZLB+NL[KPH2+X,R +M9OZ31[_"WJ:J`V^3<ZON8GI[JQK#4SOK\Z."@FLR+HZ:(R,CRP]O*AOC\RKB +M/J8NLHK*V[.[4T-C(XJKJDI^#FM3&^OK*Z\/`QJK"\KZTC("HH(+_V\/JVY" +M.F.:X@KKX]JJ6GJ36P-+`FN[`B[B#],J>NI#BZ/;:_.BB_H.$H)#J^O+2EM+ +MNTN*(H(+`WO*BFI:>IM#,VO2RLMS.SJ*NLLZ6L)[,PJ*:IL;8XLR0OI[^ZOZ +MXGKC6Z-;R^/[FC):6II*:ILC"Z,CHQOZ0AHJJ^J*HGI+VQM[6VNZNLI[H^)N +MRCN[^\K;TQOZ,FK+ZII:(JN#X]KB*YLO>WIB>FJJ8POZ*JHCH^OK&P.+&L)* +MJAJR.OL#B_KJ:JHKJVHK@SN+N^M;&VJ:0AHK"BIK.ZN+RWJZBJO+:[KZZTL[ +M"VLZ*IO;>VI*2FKZR@O+:XOC"_JB"ON[>C*:^\/S"VIK*^NZJRNZFAHKJHM+ +MFR.+RTM[JJ+B0F)JH^-;FWN;2XLK*N)"8AK*Z\L[XPL+>[OKR@KZNJ(*RDHK +MZSL+JXN[:_JBN@M+.SN[F_L[*XN*2OH:*BO+"RHJ"SMK2LHK"SJB:BHJJJNJ +M2SLJ*OL[*FK*ZLOK:HNCHTL*HOIJBXOJ"BLKZLHJRZL*6BIKJVLJ"ZOK.TMK +MJXHZZNOK:NHK*ZLK^QNKRDH*BH+NDJ)**[L;(V.#@V/C(UL;>[O+BVNKJNIJ +MB@K*RDI*2DI*RLK*"@J*:FKJZBJJJJNK*ROKZ^OKZVOKZ^OKZ^LK*RLK*RNK +MJZNKJZNKJZNKJJJJJJJKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZO_________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M_____________P`````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +M```````````````````````````````````````````````````````````` +#```` +` +end diff --git a/share/isdn/7.g711a.uu b/share/isdn/7.g711a.uu new file mode 100644 index 0000000..d7e7791 --- /dev/null +++ b/share/isdn/7.g711a.uu @@ -0,0 +1,231 @@ +begin 644 7.g711a +MZZIJ:@H*:NJ*BNHJJBMKBVMKZRNKJJJK*JLKZVN+"\L+:RNJZFJ*BHJ*:NHJ +MZBHJJZNK*ZLK*RLKZ^LK*RLK:VNKJJJJZBHJJ^LKJZJJ*ZIJZJJJ*RNKJROK +M*ROKZZNKJBJJJZLJ*NKJ*NHJJRMK:^LKZ^OKZ^LKJZJJJROK:^OK*ZKJZFIJ +M:NHJZFIJ*JHKZ^MKZRLKJZNKJJJJJZLJ*TL+BXLKJJNJ*BJJ*JHJZNKJZFKJ +MJJHJJJNKJZNKJZLK*RLK:XL+2[M+RPOKJZNKJRHJB@J*"@J*:FHJJJJK*ZNJ +M*JHK*^MKBVMK:RMKBXOKZJHJ"HJ*:NHJ*BJJJJJKJZOK:^MKBPMK:VOKJZJJ +M*BHJJJNKJZHJZBHJ*BKJ*NKJ*JNKJRLKZVMKZ^NK*RLKZRLKJRLKJ^LKJBKJ +MZBJJJNM+"^OKJBHJ:FIJZBJJJZNKJJHKJZHKZVMKZVOKZZNKJZNJ*NKJ:FJ* +MZBJJJ^N+:VL+"PN+:VOK*ZOJ*NIJ:NJJJZNKJZJJZHJ*:FIJZBHKJRIKN[N[ +M2\N+:RNJJBIJ:HIJZNKJ*JNK*ZNJJJHJ*JJKJZLKZVOK*RLK*RLKZRLK*RLK +MJZNKJZNKJZNKJZHJ*BKJZBJJJJNKJRNKJJNKJROK"VOKB^OKZ^LKJBJJJJHJ +MJJHJZNHJ*JNKJZNKJZNKJZLKJBJJJNKJZNIJZJJKJZLK*^MK:VMKZ^OK:VOK +MZRNJJJNK*^LK*ZNKJBJJJNKJZHI*:BHJJRLKZ^MK:XN+:^NKJZJJJZNJJJNK +MJZNKJBHJZNKJ*BJJJJJKJZJJJJJK*^OK:ROKZ^LKJZJJ*JHJZBJJJRLK*^LK +MJRLKZ^NJJJLJ*XLK*VLKJZNJ*NHJJJNK*^LK*^NKJJHKJRKJZNHJJJJKJNMK +MRTO+"VLK*ZJKJBHJ:NKJ:FKJZNKJ*FIJZBHJJBOK*^MK:XL+BPL+BVMK:VNJ +MZBKJ:FHJ*JJJZNKJZNKJJRLKZ^N+BXOK*^OK*RNJ*NKJ*JJJ*NKJJJKJ:NIJ +M*BJJJBOK:^MK*RLK*RNKJRLK*ZJJJJHJJJNKJZJK*RNJ*NN+JZLKJZLK*RLK +MJZHJJNJJ*JJKJRNKJZNJJJJJ*JJK*RNJJJNKJJJJ*RNKJJHK*RMK"\N+B^LK +MJRNJ*NKJ*BJKJRLKJBKJ:FIJZFIJBNHKJRKK:VN+BXO+RXOK:^NJ*NHJZBHJ +MJBOKZVLKJBIJZNIJZFHJ*VL+"\L+BXMK*^J*RLJ*:NHJ*JJKJJJJJZJJ*^MK +M*ROK:^MK:^LKJBNKZFHJ*^JKJ^HJJBKJ:BKJ*JLKBVL+"XMK"RNKZZHKJRLK +M*^MKJJLJJZKJZNKJZFIJJNJKJ^NKJZJJ:BKJJRNJ*XOK*RN+BPO+"XMKJZNK +M*FKJ*@I*B@K*:FJJ*ZNJZVO+2\N+:^MKZRNK*VMK*ZNJJZHJRFJ*B@K*BNKK +M*RKKBVO+BVMK2PMK:RN+:ZOJJZMJRKH*BJLJZHJJ:RNJZROK*FHK:QN+Z\L+ +M2ZHJ*JOKB@K*"FJ*:FIJ*NKK:^MK:^NJJVMKRVOK"PN+JZJKJ^NKBHJJJNIJ +MZNLJZLIJ*VMKJZMKJZHKJZHJJJNK*^L+"\N+ZVLJZHIJJJLKJRJJJJMJBHKJ +M:BHJ*JNJZVN+:ZLKJZNJ*VNKZVLK*ZJJJJNJZJNJZJJJJ^H*BJKKJJLKBSO+ +M:^MKZRJK*ZMJ2BIJ*NHJ:^LK*^N+*NMKJVHJ*ZJK*RLK:ROKB^LKZZJJ:NIJ +MBNH*JFIJJRHJZJNK:^LJ*ZHJ*XL+BRN+*VNK*NOKJROK*^MKJZJJZNHJJJKJ +MJBHJZNHJ*NLJBFHKBPM+:XN[*ZHKZ^NKJJJKZJJJZFMJ"BJ*JZN*JJLKBNKK +M:FLK"SMK^RJK^\I**DOKRHNKB@HKJ\HK"LJJ:FL+"XJJ&\NK*XL+:^H+*WKJ +M"RNK:ZM*ZJKZRJMZ*VNK*BH[:VNKZBN+>RN+JRI[:FJJBFL+ZXK**PHZ"JOK +M"HHKBRH*J^JK:VH+B\N[:^OKZ[JK:RI+"ZKJ:FMKJPKJZZNJRHJJBBIJ:HOK +M"RJJ^PO+*RO+2ZLJ:VJ**NJKBBOKJ^LK"@H+RKKJ:XM*BJLKZVH+2YN+Z^L* +M:RKJZHHJ:JM+*[I**XNZ:BLJ.WLK:PNKJFJ[FTNK2LL+*BN*ZSK*J@J*:FM* +MRHM*RBHKBPM+*[N+FYN+BRNKBHOK2BIJ"XLZ:FM+*\H*JBN:VJH[Z^OK"SLJ +M*JLJ*JM*JSNJJBLJNSL*BCN+*VH*:@NK:FJ**BJ*ZBN+"@J+*HL+JON[*NLJ +M:RMK*ZNZRNLJ*VLK^QL+RHKZZZL*JFOK*CKZ*\L[JBH[:RMK"FK*:HNJ"SO+ +MRDHKZ[MJ"DHKNGJZBNHJZPN+ZYN;NPK*@TO*:XI+2LJJZZ.**VKZ*ZJJ2BJK +M2BK+ZJJ+:ZM+6ZN+.RH+*XH*>JH[:SJZJDKJ.\OJ2JHKBZO*JOLK^LH+NXN* +MJCMKBJO+JNJ+:TN[2AHB*DM**KN+2NKK6FJC*SL+*NL*"NMKNHM[>[LK"EH* +M:TL*ZLM[FXNZ^LJK*[NKBOM[:HJ**BM*ZNH+JSIK:VK[J^JZJDOJJWKJ2_IJ +M"\MJR\N*6QM+RTLJ&BNKZZKJ:JJ+BSJ+ZDIJ2RJB:_MJ(JJZJDJK&RKK`PO# +M2XMJ^BOJ.RI+:AIJ"AM+*HOJFY)2JJIK:JN+BXMJJVIJ:J,;^\N:VRIK.SIZ +M^LKJ.FOCR[MKBFM*NNNZJBOJNDO+:P.K*DM+NHO+"YIZ(RN"0AH+*CJ+:ENC +MZX,#^LI*BF+*.TL;2\LK2TN+>XOK2VKKPIKJ6JLZRFI+&F)+&[KJ6_I[NWKK +M8ZN"JLK[.ZI+NW-KBFNJTJJ[JZHJ:\H*R_L;:EN+ZFLJ"LHK"NMKJJH[FNI* +M.TIJJHJJJHH:JNHZ*KM*(QO;BXK*RZMZ2XI+PV-K:^NZJXO::T,J^FL*`AK* +M>@JKZHIK:^H[&_JK(WMZ^FN;RZK*:UNJ.NIC^XK*:FNJ*HJJJFN*JNJ*:KK: +MFHKJBFL[BXN;FPO+^]O+BVIJJON+ZILCNPI*:@KZFEIZZJL*FLK*FAI**HH* +M2LJ*"DHJ"ZNZJZ-C8U./+^\/+S/#6_O+:^HJ*[MKNB)"<BZ^?GZ^#H[N4D*" +M<N[N\MHZBHL;K[]/;T^?GQ\?/V^G.4&!5Y^G*@C@0`"@N#@([H?75U>7]P=# +M_F;>YI;VO@LO3T_?A^=S8FY._GZ>ON)S7V=W@8WM&1<72Z"0+*P`>'AH?YFA +M&?GI9R\^:+C(B"C&P@_']T<GSWN2)L8&?C+BHING]ZF9+;V1Z;>?R!#L;)"8 +MZ"A[66&A.1<;'I;X6$CV)BYO-U?WGPL:LM[&ACY"*P/O#[^GARFQS6WYYV<F +M0"SLK*#6=F[)@>$Y=PN&UK@@.";B8E-WJ3>O;AX.GK8&4@LCK[]/3[\?-V$- +MS2$GAS)@+&PL8#;F+FF!83D'+M:(."#89C_GYW<I%S\>*!8FYL8.\Z=GGQ-C +MTP^G^>V]<4=?NQBL;.Q`%N[B=V$!F;?NZ#AX6!@VOW?7*:G'+_XH*`8FYBZS +MO]]_$P/#F]-)K4VMZ:=3"!!L[/#HTLI'H0'9M[[HN/AX>/;#1Y>7]R<O[A:H +M!DZN"J-37_^+VFIK=Y&];;F'!T;P;(Q0N$(*YZ%!X2D2B'AX>)@H"_<IJ9=G +MDTZHB%:F+GH3YP>GHVZ.ZY>Q38U9E_?^0.QLK-@^ZE^906%I&F@8V)AX**HW +M*=?WYT.^J.CV'A*:8S\G'QORHN^I0<T-X;?GIL`L;*P@?D/G.0%A"2IHV%BX +M"*ANIZG7MY_[[@86=J8":ZOJ,X]CRYNGH6V]T5?_:T@0;&PP%B,?J2$!6<=& +MF*!X".@&^N<7=Z=;.@Z&]L;.^KIB"M-_O^^/*7%-#>&_RT:`+(PLH'(/YPGA +MX<F+B-AXZ%:H]BMW%Z?C6\,*7K;F4C)^GDJ_YX?G1R%MO1$'LEXXD.SLL,;_ +MI[=YX1G'1GAX5L8HB"8?1Y_+J],OTO;VO@+.'O+/]_=GA]GM/:TI8IX(,"QL +MD.C3IR<)H=DISK@8J)ZH."BCMR<;*_\'&[;67M).'O)/]Q>WAPE1O6WY>^Y6 +M`*QLK%BN#T]7>=E)SY9(J/[6F#C>C\^#@U]WY^YVQ@X^)KY;9Y=W1TE1/6T9 +MP\ZH@-!L+"!>DV\7^1DY!Z:(%B;H&/A&:O,3TR?W)V*&9GX^3D(CIS>7UXGQ +MS6WAY\+V(/`L+$!HKDI?Z;EY:6^FWDYHH%B(AO)C+P<I5^]N#HY^/JYZPR?' +M1ZD!C8U!:;.^.`#0+'"@%IZ+1^GY^>D_>ZJV^*#82-9^RM^IZ3>/VSJND@*Z +MVT\G9T>YD>UQV3?39OB`$!!`&.@V,F^7"4EIEP?KEK@8>$BHYNJ'5Q<'IY_O +MD\/;8R_/[X]_UV$Q@3DWG^(6^(#`8)B(*+;^.V>7J5<WKPZV5JBHEB::CY\? +M?Y\?GY]__]^?#S-C0\//*1DY*0<_2[X&Z+BX""BHEN;."E.?#VN"KF[.3NZ" +M*^.S<R^/C\__/_\_S^_3,S.3<V/+\[<I]Y_CBUJN/L86%D8F)B:F3D+B0E*N +M0CIK.SL[HR/;6^,SLT.S<R\OTQ-3+Z^SHZ.C.S-GM^>/HXLZ6@).)F9FYN;F +MYJ:>3BY"XCHKNSN[>YN;&Z/#@^-#T\^_#V]OSX]3@]N;B^KKCZ=/`PL+JGI" +M#AY>WOZ>GIZ^KO+"\O(B.DKZBHN;X]LC0T.S+Z_O[^\/+R\30R/[2ZM*FNIO +MW[_SN\MJ2OI2/GX.KN[.GIZ^SLX.+D+:NJH+2YNC0Y-3K^_/O\_/;Z^3$\.C +M>ZMJ"KI:.K._;X/+RROJ2@)2;F[NSG[>GL[NTE)R`F):2NL[&T,34R\O+U/O +M;R^O$Y/#PX.;>\MJ>EK+SY\/,R,;JWJRCC[^SHY._M[^CBXN4O)B&LHJR]N# +MPX.S,Y.OC\]O;V]OTP.#VTO+*TK:B[_?3T,[B\IZ`H[^?@YN3IY>/HYN[BY" +M@OHJJLL+2R/SKP.3+Z\O4V\O+U/SD_-C>QL+VW\G__,[RPJ:\K[>IGX^_GZF +M7MX^CFZ2`LIK.YO+RUMC6Z,#T_^?/P]/OZ\3,S-C^^O+_P?GOX/;J]I2GF;& +M9J9>7IX^3FXNKG)"6LIJRR.[^UL#8V.SXR\_OP_/OV^O\^-;&P_W%\?_4T.J +M8DX&=I8VMD:&I@[2LE*N@IKZN@JK:UO;:WM[LQ.3;\]/CT\?CV_OKV,#MVFI +MAT_ONX).1J@H5A;6ED:FTNL;*ZK+RPLJ2IIJ2VL*NBMK>Z.S;P^_WS]/#\]O +MXZ>).>G'WX_[+@;HR`AH*"C6MMX*3^?_\_OJ.G).?HYZ*@KZ"AOS[P_/#S_? +M_V^O<[-OU]G9B?>'7ZJ>*'@8>$A(""A&$M.G9Y<I]R^"_N9&1L:F`IOC(R\/ +MCV\/3^\O4W-3KZ\?N6&AR9>W_[+&N*`@V'AXR"AFN^<WQS>IJ><:YD8V]I8V +M7BJ//W\GA^=_K\.;JGI"PCKS"<'!60GI=\MFN"#@(-C8N"CF^\<7MP>'I_^O +MXN:VQ@:&)DZ:4^<'!X=G7Z^+>O*.SFXRBA/I`4$AR6FI<Z8((&`@V%@X*"9+ +M!Y='AV>?\[MB?N9F9N9^;MJ#WP?'1V>G/[.Z[DY.SFX26@N'6<'AN6F)1VJV +M^"`@V%@8"':>PV?GYX?GCZ-J6EK"#CXN6KK*BY.?YR<?GT]SBQIR,F*"TBZR +MHCI/B7D)UVG)]V_ZQFB(:+A(:*CVGJ[N`DLC8]/OSW__;P,+.AK:.@L#4V^/ +M+Z^3LR-+:VH:`I*N;FZN+I*C1T>?5[GI]S<?N@)N-M8VEJC6UJ@6!B;^XDMS +MCX_O#P]3TZ\S<V^O`T/3TU,OTQ,O4Z/KNN+2;LX^GE[>,M_G$_>YB?=W9\NZ +M<D:61O96EI96=F8F/L+KLP^/4^^/[Z^OK^^/+W/S4Z]3+X\/CQ-+&K(NOAX> +M'GX^3DX^DK_WG^=)N=<W1_.Z"IXV!N8V=G:H5D9FIFYZ&R\OHP/O[^^/#S^? +M3U/SL[.34U.O+U-CJF+2;C[>7GZ^OCY.[JZNN_=7)ZEYB<>'/SH:<L8VAD:6 +M]A:HMJ8^<JI;[T^S:WL#LZ\/;_^G#V/#,V.#L\.S<R,*,B[N[NXNTC*"LH[. +M[K*R`MOWJ5\W26EG)S_JNF)F1H:V%G:6%@9^CJ*K"[,ONSI+8X.3CX]/'[^3 +MP[.S$Q-#(]L["H(2$O)"8MK:(N("\M*RVCK:NA]7)U-7B<<_3PNB.OZVAF9& +M1L8V!GZ.,LHJ.]-#ZBH;VR,STV]_/V_O[R]3,V-CX[NJ.B)B8C*N\H+"@K*2 +M0N(B@EJ*>F)[A\<OAVDIAU]O:^I"IF8F9@;&-O:&ICZ2(LKC,XL*"_N;`Z_/ +M?]\_S\\/C^^OKR]S>^H:0A(N#@Y2$J[NCFY2\C)"FJKJ>MM'=P^'">G')\^[ +MZP(FAN8&Q@;V=@8F?M(B>IL#*J)JR[NC\R^?Y]]/?U^?OP_O;Z_;"N(R4FX^ +M?LYN;@X.;G)BXN*:J@LJZK^79[\7:9<G/]LJ:H[FYH;&!D;V1B:>KEI:"AL[ +M^IKK&\/S+S_?W]_?WZ>G'T]O$Z,J`FX.#C[>WGZ^SLZ.<IJ*JVL+^Z.CR^J; +M)W??OY>I!_^OJ@KZOB8F9@8&MO8&IOZNHAHK6XOZBCM#K^\/WV?G?_^GIY_/ +MTP/C:V+N3DY._AY^SNY2<O(".HH*:NL+2\OK2S\WYS\WJ?>G#WNJRFZF)H8& +M!D8V!B8>[N+:ZEL;*BH[`Z\/;\_?IW^/;\^_CW,#(SN*8E+N[NX.S@XNDJZN +M`AHZ"JNKB]L;*ZN;SX=?O\<71Q\O2^I*[MZFYF9F!K:&'KZNHCHKF[LJJCOC +M<^^/SW_??\^/#\^/D^-[ZSH"TJXN+F[.;JX2$G*R@IJ*ZBJ+VV/;>WOSW^?_ +M_P=')\]#BVHB#GX>)N;FAH8FGD[28B)*N\LJ"Z.S$Z\OCS__3\]/3P_O\X.C +MR\KB,A*N[HZ.[J[2$A*R8AI*:JI+>SM[>SM;#R<?_V='9Y^O>VLZ+CX>)N9F +MA@;FIG[N`AHJ2PNJN^.S+X\O#W\_#P^/CX\OLX.C"PH:`K(RTNXNKBY2TM)R +M`J+:>HHK2_L;(X/#+_^?_W^GI_^OV^NZ0NX./AZFIEX>?K[NLJ(Z*NN+2]OC +M0U.34P\/[X^/+Z\3LX.CRVKZXK+RDM+2DC+",I(RXIKZ^FJ[VWO[V^.#,P^? +M3[]?I[\3&RJZ`FY./AZFIB:FGLXN0IH*Z[N[.WOCD^\O+P^_SX^/+Z^O0UN; +MRPK:`G*2DE*NTA(2,K*R8MJZ*HN[6X-C@X.#`X,CX_/O[U-3KY-C"VHZ@A+N +MCLY.OKY.SHZNLB)ZZCM;(X.3+Z\O[R]3<P,C>TL[NPOKJRK*.AJBVMI:HN+B +M6GHZNHKK"\L[>QM;VYO[NWN;RVO+V]L[NYLC&VOJZ@J:XK(2TM)2KE+20B(: +MNFJ+&X,#(V,SLR-[FYO;FWO;XUO[.TL+*VI*2@JZ6F)BHAH:&CH*JVN+BVM+ +M.SN[:TN;>\OKZRMKZ^JJ.YM[.TM+2^MJRLJZ.GI:@N*B6B(B6IHZ^OH**JJJ +MZPN[F]NC(Z/C0V,;(X.C&SL+"\LKRLKJ:HH*.IJ:^CJ:6IJZ2DH*:JN+B^N+ +MR[O[.\M+NTN[.PMKRTMK:KKZ.IHBXJ+:FAK:&CJZ2NHK:TO[>QNC(Z,C@X.C +MHYN[^WM+BPOKJJJ*.GHZ^IJ:VAJ:&AHZ2DIJJ^L+N[N+"[L+*ZMKZRMK"XL+ +M2XOKR[L+BVN+B^LJ:HI*2LJZNDJZ^OIZ^DK*"NJK:TN[2SN;6UO;6]M;VSM+ +MNXLJJJL*.KI*2DJZ2HH*2DK*2CIZ>KKJ*BKKNWO[^QO;HQM+R[O+JBKJ"HIJ +M"LK*:JJJZHIJJZMJ"BKK:RLJJFOKJBMK:TL+*HHJJFJ*BBIK:VN+"XL+2POK +MBVMKBZNJJNH*"LJZ2NHJ:BHKZRLK*ZOK:RNJJRKJZBHK*RN+"POK*ZLJJZJJ +MZVMKBPMK*BHJZHK*>OIJ:HKJJBOK*ROKBXN+:VOKZXO+"RLKZVNK*JJJJBHJ +M*JNJZNJJ*BHK*@H*B@J*ZJJK"POK"[O+"\O+"RLKZRLJ:NKJ:FKJ*BKJBBHK +MZHHK:ZNJZJKKZRLK:\MK*ZOKZ^LKJZJKJNKJZJKK:ROJJJNJJFIJJRMJRHHJ +MJRLK*XO+RXOKZROK:RMKBVLK*ROK*RJ*BBHJZNKJ*JJJ*BHJ*FKJJJOK:^N+ +MB^OKZZLJ*JJKJZHKJRJJZZLJZBJK*NJJJJLKZVL+"^LKZRLJZNKJZFHJJZKJ +M:BKJJJNKJROKJZJKZXMK:[L[:^N+J^JKJZJKB^NJ*@H*BLJ*:HKJZ^OKBVOK +M:VNJ*BJJ*BHJJRNJJNMK*ROK*RLK*JKKJFKJJJNJ*NHJ*RN+RPL+B^L+"ZOJ +MJBIJB@KJJBKJJRNJJBNKJBJ*ZJOJJROKBXOK*XL+ZRHK:RLJZJLK*BKJJJLK +MJBJJZFHJ*FKJJJNJJRMKRPMKBXN+BXLKJBJ*.KK*"FJKJJOK:RLK*ZIJ*BKJ +MBBHK:VN+2YL[2SM+"VOKJJJJZHK*RLK*"HKJJBHKBVLKJNIJZJJJJRMKBXOK +M*RLKZVLKJRKJJROJ:BNKJBMKZVMKZPN+ZVN+JNHJ*NH*RLJ*:FIJ*JJK:NHK +MJ^NKJNL+BVN+B^MKRVOK*ZOK"VNJZVNKJJLJBHK*RNIJ:JHJ"HHJZFJJJRN+ +MB^MKZZLK*^MK:VMKB^LK*ROK*ZHJJZKJ*BHJZNKJ:JLKZFHJ:NJKJ^N+:PO+ +M"XOKJJHKJBJK*BJK*JIK"RNJ*NIJBHKJJJJKZ^NKZVN+"XOKR\OKZRNJ*RMJ +MZJLJ*NLK*FN+JRKJZBOJRLJ*:BKK*@IKRRMKBROK"^NJJBNKJVJ*JJNJ*NHJ +MJZNJJBMK"\LKJBOK*HHJJBJJ*JJ+BRLKZ^MK:ZOJ:FKJJZHK:VOK*BHK"XLK +MZVLK*ZJ*:JNJ:FHJ:RNJJNKJB@K*"FKJ*JLKZVO+2PL+BPL+:RJJJBJKJRJJ +M:RLJ*ROK*^KJ*ZIJ:BJ*:NHJJ^NK*VOKBPOKZPN+*ZHJZNKJ:FJKJROK*RJJ +M*^K*BBIJJZNK:\M+BPL+"^NKJZJKJBLJ*BKJ*JHJ*BLKJNIJ:NIJZNKJ*HH* +M*JNK*^OKBPL+R\L+R\N+*^L+*ZJJ*FKJZHIJ:@K*"@J*:JNK:[L["XO+2^NK +MJRHJJRIJ*NKJ:FIJZJJK*VN+"^LKJZHJJJHJZVMK:^MKB^LJ*NJ*B@H*BNHJ +MZBHJJJOK*^N+NTO+2TMK:XLKJROJZBIJZFJ*NHKJ"BJJZBN+ZVMK*RN+BXL+ +MBPN+:VMKZZKJBHKJZNIJZBHJZNKJZJNJJNL+*ZJK*RN+ZRL+B^MKZRHJJXJZ +M"@I*ZBNK:PN+"\N+:XLKJNN+JZJJ"HHJZNKK:ROKZZLJZNHJJBJJ*^OKZVOK +M*^NKZBHJZBJJJZJK*RHJ*NJJ*^OK*ZLJ*FKJZJJKJBJJ*^OK:VN+RXNKJJNK +M*BJKZXN+JVJJJZIKZRMKZRNJB@H*BFIJ*BHK*RNK*VL+B^LKJZJJZHIJZNJJ +MJ^HJZRNJ*VOK:VNJJ^NK*FIJ*FMKJBHKJRJJJNJJZRNKJZNKZVOKJZLK"ZOJ +MJZNKZ^LK*ZIJ:JJ*RBIK*ZLKJJN+:RO+2VMKJFIJZBJJJJOK"VNK*ZKJ:FIJ +MZNJJJZNKZVMKB^OKZXMK*ZNKJNIJZBHJ*FJJJZHJJ^IJJZJKZRNJZ^LK:PL+ +MRPN+BRNJJZIJBHJ*ZNIJ*JLJ*BLKJ^NKJBLK*BJJ*VOK*VL+:XL+B^OK*ZJJ +MZHJ*:HJ*:BKJ*JNKJJLJJBNKJROK:POK:\MK*RMK:ZKJ*BHJJJHJJJLJZNKJ +MJROKBRNJJJJKJZJJ*^OKZ^NKJRLKZVNKZFJ*:FJ*RHHJJFN+"PL+"PN+:^MK +MBVMKJRJJJZHJJZMJ2@J*:FJ*ZJNKJZLJ*JJKJBN+BPL+:^MK:VOKJZIJBHK* +MRFJJJZHK:XL+"XMK*RLK*RJ**BNKJ^MK:^LKJZNK*NJ*"HJ*ZBJJJ^MK:^NK +MJNM+ZZOKJBHJ*RNJJZNJ*JHJ*BKJ*JLK*^MKZVMKJZNK*RNKZRNJ*NIJZBKJ +MZJNJJZJKJVOK*^OK*ZJKJZKK:^OKZ^NKJ^J*ZJJJJROKZ^OKZ@HJJJHKZVMK +MZVLKJJJKJHJ*:FK*RFHJ*BMKBXMK:^NKJZNK*JHKZRLK:XN+B^NJ*BJ*BHH* +M2FHJ:HKJJBN+:VO+RPL+"XN+B^LK:RLJ*FHJ*ZKJZHIJ:BKJ*JHJ*JJJJJJJ +MJZOKBPO+"XMK:ZLJZFKJ*BKJJBOKJRLKJJJJZNHJZFHJJJHJ*VN+ZZOKZ^LK +M*JKKZ^MKZZNJJRKJ*JJK*^J*JRNKJZJJ*^OKZPL+BPLK*NHJZNKJZBJJZNJK +MJRHJJBHJJZHJJ^NKJZNJJBOK*^OK*VN+*RLKJZNJ*BJJ*BHJ*BMK:^LKJBLK +MZ^LK*RNK*^NKJ^NKZFHJ*NKJ*JJKJZNKJNKJ*NKJ*JLKZXN+:VN+BVOK*RNK +MJNHJJNHJ*^OKZ^LJ*BIJBFKJ:FKJZJN+ZVL+"^NK*RNKJJHK*RMKBXNKJNNK +MJJNK*FIJ:HJ*BFIJ*JHKZRMK"PN+BXMKBXOKJZJKJ^NKJRLKJRKJ:HJ*RLI* +MRHIJZJJKJVL+"PO+2TL+BVOKJZLJ:NKJZBJKJZLKJJMKJBLK*BJJJNHJ*JOK +MZ^MK:PL+ZZJKJRKJ:HJ**JHJ*NMKBVOK*ZNKJBHJZBLK*XMK:^OK:^NJJJHJ +M*NJ*"HIJZBHJJROKZZNJ*RJK*ZJJZNJKJZJJJZNKJRLKZXO+BXN+:RNKJZLJ +MZJHJ*JHKJJJJJRNJ:FHJZFHJ*JJKJZKKZRMK:^OK*RIJZJHJJROKBPL+B^NK +MJBNK*JHJ*NHJ*JKKZZJK*FKJB@KJ*BJJ*^OKBXN+"XL+"VMKZVMKZZLJZFIJ +MBHIJ*NIJ:BKJZJHJJJLKJZNKJZOKBVMKBPL+R\L+:^NKJJKJ:HJ*:BKK:^MK +MBZIJ*NHJ*NHJ*JJJJJHKJJOKZ^MKZ^OKJRKJ*FKJJJLK*RNKJRKJ:NKJ*JHK +MJ^NK*^MKR\O+"XMKJZLKJZHJZHH*:FKJZBHK*ZNJJZLKJZJK:XLK*ROKZROK +MJZJKJRHJJNIJZHJ*:FJJJZNK*XO+R\M+2\MK*ZKJ:HIJ:NJJJZHJZBJJ*JJK +MJJJJZBHK:^N+Z^MK:^MK:^OKZRNK*ZLJJBH*:JHJJNLKJJNJJZNK*ZNK*ZNK +MJJJKJZNKJRKJ*NKJ*JNK*^OK:VMK:^LK*ZNK*ZOKZRNKJZLJJZKJZJHJJJKJ +M*BJK*^OKJRIJ"HKJ*JLK:\O+ZVMKZROKZZLJJJOKZXL+RXLKJZHJ:HJ*"@H* +MBNKJ*JJKZ^OK*ZLJ*BJJJJLK*ZNK*^MK:XN+:VMKJRKJZFKJZNJJZXN+BPN+ +M:RLKJRLK:@K*NDH*"FJKZ^LK:VN+BPO+R^NK*NH*2FIJJXL+2\N+*RNK:NKJ +M2OHZRFJKZ^MKBTL[*VJJJJJJJ^N+.XLJJZHJZBMKZDH*ZNL+JZJKJNJK:^M+ +MFS.+OM)+F^NFAO]WBIHJHF>'KD:RMZDF*&[GJ6L6Z+Y'IX*B<R..WA+O?Z>[ +MIHLOPIY>OM/W/Z<G.^JOJA+Z#BXJ.T*F9G[J&^/OOP\;^L)+@TK""Z]/SX.K +M*UHB^GX.^BH**^LB@U/BZMOZ&P-#>II3>U.;,O*Z8LXRRZ_#NN[JHR.3.ZKR +MJMNZ2VJ[6[.;HOL+HEKRH@):NZK+8T.3<\LB>UL"KBY:*JNJZDOC:TM["\IZ +MJBI+2MK[`R.Z8EOCVPNZ"TL*.CJBFNOZ2Y,;RFKJ&LH;:F)*J\MJRHHJ`[/K +MFKHC&\M*(N.#BP)BN_NJ^NK;BGJZ(EH*^ZL+J^J+2_OJ*XJJXX/;RKHJJXN+ +M"LHJ"DOCPZI:BZH*^GJ:*COZ^OM+"SNJ.FI+2VO:6BI+FZJ+"RH[BPJB*JOZ +MBXL[VPM[2RM+R@+ZNRK:NFJ+>WN*2JHJ2NH[:PHKRHN;JXH+F[L[ZCJ+"XIB +M>FO+"ZN:&ON#RPH*.CO+BFHJRZNJ2ZO*RHO[2ZO**CL+RHJJ"XJ:.@J*NJMK +MJB-+:YO+:TJZ"FIZB@OKR\LK*VLJBBIJZTOJRWL[.ROJNBKK*ZNZ.LKJJVKJ +MRPLKJPH*2NIK*NK*BZ,;^[NJZRN*JFJ*2FI[:PMKZFO+RZKJJZO*>J+*ZHOK +MZPNK>\L*2DJZJHNKJSM+JRJJBRMK*PJJ:XMJJJH*JNMK*^HJZZOJJJH+>\OK +MBTOKJ\IJ:LKJJVLKBZHJZVH*ZHKJ*VMJRFO+B^HJ*XM+ZNH+.RN*:BM+ZPH* +M*VL*"DH*JXN[:ROK"ZJK:ZLKJRJJJJJJ*ZKJJBOKJHKJJFNK:HHK:^OKJPN+ +MZZHJZUINTN+ZJLM[6R/C8^/CH]N;^[O+BVNKJBIJB@K*RDI*2DI*RLH*"HJ* +M:FKJ*BJJJJLK*ROKZ^OKZ^OKZ^OKZ^LK*RLK*RLKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +9JZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +` +end diff --git a/share/isdn/8.g711a.uu b/share/isdn/8.g711a.uu new file mode 100644 index 0000000..1e0fb02 --- /dev/null +++ b/share/isdn/8.g711a.uu @@ -0,0 +1,322 @@ +begin 644 8.g711a +MRVLJ:NJ*"FKJ*BHJ*BHJ*BJJJZNKJZNJJJLKZVOKZXN+B^LK*ZLJ*NIJ:FKJ +MZNHJ*BJJ*JNK*^MK:RLKZRLK*^OKZ^N+:^OK*RNK*NJ*BHK*N@J*BJHKZVL+ +M"PN+:XN+BVOK*RNKJHI*:BKJZNHKJZJKJJNJJJHKJZJKJRMK:XMK:VOK*RNJ +M*FIJ:NKJJBJJJJKKZRNKJNLKJFJ**JOKJZLK:JMKBXOK*ZOK*RIJ*NLK*^LK +M:^LKJRHJJ^HJZFHJ:JJK*BIJ*POK:VOKZZNKJNJJZNHJJBNK*^N+:^N+ZRK* +MBBKJJZHK*ROKZ^MK:XN+*ZOK*ZHJZBJJJRIJ:BHJJBHJJRNKJBKJ*BOK*VN+ +M:VN+"RNKJZKJ:FKJZBKJ:BJJJRNK*RLK*ZNJ*JHKZVMKZVLKJRLKBVLKJJKK +MJBKJ*JHJ*HIJJRJJ*VMK*RHJJBNKJBOK:ZOJ*JN+"^LKJJLJBNHJJJOJ*BHJ +MZNJJ*RMK*ZOKZ^LK:\N+BRNJJJJJ*BJKJZJJ*BKJZNIJZNKJ*JJJZ^MKNTMK +MB^LKZVOKZ^NKJJHJ*JLJ*BHJ*HH*:BHJJJLKZ^OK*XM+N\OK:XOK*BJKJZHJ +MZBJJ*BHJZNKJ:@J*ZJJKJ^N+BXN+"POK*RLKJRKJJJH*"NIJB@J*ZJLKZVO+ +M2PN+:VMK*RNKJZOJ*BJK:VN+:^MKJRJK*BHJ*BKJZNIJ:FHJ*BJKZ^LK*RLK +M*ZNK*^OK*ZLKZ^NK*RMKZZLJ*BKJ:BLKJBNKJJHJ*BJK*RNKJZNJJJNKJ^OK +M*ZOK:VLK*RLKJRJJJRKJ:NHJJJJJ*^MKBVMK:XN+ZRNK*ZLJ*NKJZBKJZJNJ +M*BHJ*NHJ*JJKJRLKJBN+B\M+B^LKJJHJ*BHJJJJK*^LKJBJJJBKJZBKJ:FKJ +MJ^OK:PO+"XMKBXN+*ZJJJBKJZJJKJRHJ*BKJBHIJ*JJJJRNKJROKBPL+"\O+ +MBVN+ZRJK*FJ*"@J*BNHJ*NHJJJLK:XN+:^NKJZNKJJOK:VOKJROKZZNKJZKJ +M:HIJ*BJJ*RLKJZOK:VMKZVOKJZNKJZNKJZOKJRHKZZNK*BHJBDH**NIJ*JKK +MBXL+BPN+ZRLKJBHJJRLK*RMKB^NK*NKJ:HH*BNHJJBLK*RLK*ROKZROK:XMK +M*ZJK*RNKJJJKJJNKJJKJBFKJ*JJKJRLKJBJJ"PMKRXOKZRNJ*NIJ:HIJZNJJ +MJZLKJZNJ*NKJ*JJJJROKZVL+RPN+BVLKJZNKJZKJZBKJ"FHJ*BJJ*^LKJROK +M:^LK*^MK:XO+R\MKJ^KJ*HJZ2HH*:JJKZRLKJZJKJJJJJZHJ:NJJJZOK:VMK +M:^LK*^MKZZNJJRHJJZNKJJHJZNKJZNJJJJJJJJNKJZLKJZLK*^MKZ^LK*ZNK +MJJNJJ^NKJVNJ:JNJ*BJJ*ZLKZVOKJBKJ:BJJJJJJJJNJJBHJ*[NCN\IJJHL* +M^@IJZDH*JXMKJZIKRPNKJ^MKJ^HJ*^LKJVN+:ZKJ:FIJ"@IJZNKJZNMKJRN+ +MR\MKJ^N+:VOK:VLKJBHK:^LKZ^LK*FIJZFJ*R@J*:BHKRTO+BVLKZHJ*:JJJ +MJJHKZ^MKBPMK*ZHJZFIJZBJK*RLKZXN+*RN+"^NK*JOK*HHJ*FIJZBIJBFJJ +MZ^N+BXMK:RNKJJLKJZNKJJNJJ^MKZRLK*ZLK*ZKJZNJ*"FHJJVL+BXMKBVOK +M*RLK*RJ*BNJJJJNJJJNJJBLKZZHJZ@J**FHJJBMKBXL+B\L+"XOK*ZLJ*BJJ +MJBHJJJLKJRHJ*BJ*"FHJ*BHJJZNK*VO+2PL+ZRLKJRKJ*JNJ*NKJJ^OKZVLK +MJBKJ:NHJ:FKJZFJJ"\O+.TN+:ZOJ:NHJZNKJ*BJJJ^MK:XLK*ZNJ*BHKJRHJ +MZJNK*^MKBXLKJZHJJBKJJZNK*NJJ*RLK*^OK*ZKJ:FJ*:NHJJJJKZXL+R\M+ +M2^MJZJLJ*JJJJZLJ*BJJJJJJJBHJ*JJJJ^OKZ^LKJZNKZXN+BRNJJJHJZFKJ +MBHJ*:BHJJROK:ROK:VL+"PL+:VMKZVOKJRKJBHH*"@H*BFHJJHMK*XMKZ^OK +MZ^OK*^LKJBIJZFKJZNHJJJOK:XN+BXMK*RHJ*JJJJJHJ*BHJJZMK"XMKZRNJ +M*BHJ*JJKJZNKZ^MKZRLK*FIJ:NJJ*JJK*RNK*BN+:VN+ZZLKJJJKJZNJ*BIJ +MZJJKJZJJZ@H*R@KJJ^OKZ^OK:PL+"\N+:ZNK*ZNKJBKJZNKJ:FIJ:HJ**JLK +M:XMKZ^MKBXN+:VMKZ^LK*^N+J^KJ:LK*"FKJ*BJK*ZNKJJNK*RLK*RNKJJJK +MJJHKZ^MK:RNK*NKJ*JNJJRLK:^OKZZNKJBKJ:NKJ*JHK*RNKJRLKJZLK*ZLK +MZ^MK:^OK*VHJJRHJJJNKJZLK*ROK:VN+ZRNJJJNKJRKJ*JJKJZHJ*BHJ:@J* +M:NKJ*JJKJRMKBVMK:VOKZ^OK*ZLKJZNK*RLK*RNJZ@H*BHIJZBJK*ZMK2\O+ +M2PN+:RLJZNJ*:FIJJJJJJZJKJRHJ*JJJ*JLK*^OK:PMK:^LKZRLKZRNK*BKJ +MZBHJZNKJZNHJJRNKJ^OK*ZNKJZJJJJOK:XN+"PL+"VLJJJKJ:HJ*BHKJZNKJ +M*JOKZRNKJ^OKZ^OK:^MK:VN+:RNJJJJK*NKJ:NKJZNIJZBHJ*NHJJJLK*^OK +M:VOK*ROKBPL+B^NK*BKJZNIJ:HJ*:JHJ*BNJJROK:^MK:^MK:^OKJZJJJJNJ +MJJHJ*JHJJJJJJBHJZJJKJ^OK:PL+"XN+:VMK*ZNJZHH*"@J*:NHJ*JJJJJLK +MZ^OK*ZNJJJLK*^LKJNMK*VOK*ZNJJBHJJBOK:^LK*RNK*JJJJJJJ*NKJZBJJ +MJRLKZRLK*ROK*RLK*^LKZ^OKZRNJZNKJ*JKJ:FKJZFHJ*NHJJJNK*^OKZVMK +MZ^L+JRHKJZJJZNIJ:FKJ:BJJJROK:^MK:^LKJZOKZ^MKZVOK*ZNKJJHJZFJ* +M"LH*:NJKZVMK:XN+:VMK:VOKZRLK*ZNJ*NKJZBHJJJNJJJJK*FKJZHHJJJLK +M:XL+"POKJJJK*ROKJZHJZNHJJJNJJNKJ*BJJJBHJZBJJJBLKZXL+"PN+BXL+ +MBVLKJVJ*"FHJ*JNKJBKJ:FKJ*BKJZBJJJBN+^[N[NPN+ZZNKJRIJ:HH*"HJ* +M:BHJ*BHJJRLK*^MKZRLKBPO+"XMKZ^LKJZJJ*BJ*"@H*BFHJJJJJJZOK:VMK +M:VOK*RLKJRLKZ^OK:VOKZZH*BFH*"FKJ*BKJZNHJJ^MK"XMK*ZNKJZNKJJJJ +MJBLKZRNK*^NKJBHJJJLKJRHJ*NJJJROKZ^OK*RLK*ZLKJZLJ:FKJJNMKZRNK +MJNKJZNKJJNNJ*JNJJBLKZ^OKJZNKJZNKJZLK:VMK:RNKJRKJ:HIJZBJJ*BHJ +M*JJK*ROK:VOKZXN+:^OKZRNKJBKJ:NHJJJNK*ZLJZNHJJJJKJJNK*VLKJFL+ +M"\L+ZZNJ*NKJ:HIJ*JJJ*JJK*RNK*NKJ:FHJJRLKZ^OKZ^MKZRLK*^LK*ZLJ +MJBKJZFKJZNJJ*VOKZ^NKJBJJJJLK*RLKZVMK:XMKJZLKZHHJ*JHJZNHJJJJK +MZRNKJZNKJJHJ*BLK*RLKZ^LK*^OKJRHJ*JJJ*BHJ*NJ*BFKJ*JHKZVMK"\L+ +M"VLK*ZLKJZJJJJNK*BKJZFIJ*BJJ*@KJJBJK*^N+B\M+RTL+:RLJZBIJ:NJJ +MJJJKJZLKJZNJ*FKJZNKJ*JOK:VMK:XN+B^NKJRLKJZNJJNKJ*BJJJZLKJZHJ +M*NKJ*JJKJRMKZ^MKR^LK:RNKJZHJ*JHJ*JHJ*BHJJJNKJZLK*^OKZRLK*^LK +MJRLK*RLKZ^OK*ZNK*NKJ:NHJJJNJJBHJZJJKJZHJ*BHJJ^MK:VOKZVMKBVN+ +MBRLJJJLJ*NJ*:FH*BFJ*:NHJJJOKZVMK:VMK:^OK:VMKBXMK:VOK*ZLJZHIJ +MBHJ*BFIJZBJJ*VN+BXMKZROK*ZJJ*BHJ*JNJJRLK*ZNKJBIJZJNJ*JNK*^OK +M:XL+BVLK*RNKJZHJZFKJ:NHJ*JJJ*BKJZBJJJJOKZ^LKZXL+RXMKZRLK*ZNJ +MJZNJ*NKJZBHJJZNJJBJJJBJJ*JHJ*JJKZXMK*VN+ZRLKJZNK*RLKJZKJ:FIJ +MZBJJJZNK*RLKJZJKJZJJZNHJJROK:XL+BVLK*ZNJ*BHJZFIJZBJJJZLK:XN+ +M:ZLK*ZNJ*BJKZ^OK*RNKJBMKJJJK*NIJBHJ*:NJKJRLKJJJJJJNKZVMKB^LK +MZVMKBPL+*ZHJ:FIJ:NHJJJNJJJJJJJJJJJNK*RLKZ^MKBPMKZZLJJJHJJJLK +MJZJKJZJJ:LJ*B@KJ*JJKJROK:^OKZVMK:^LKZRNKJJNKJZNJJJNJJBKJZNKJ +MZNHJJ^L+RTM+R\MKZZLJ*NHJ*BHJ*BHJZNKJZBHJ*JNK*RNKJBOKZRMKR^OK +M"PL+B^MKZZNKJRJ*B@K*"HKJZBHJ*BHK*^MK:VOK*RNKJZNKZVN+BVLKJBHJ +MZBKJZNIJBFIJZJJJ*VMK:RLK*RNKJJJJJ^N+RTM+2RMJ*FK*R@IJ:FJ*BNJK +MJROKZ^LK*ZNK*ROK:^N+"XMK*ZHJBHH*RHIJBFHJJJJJ*RNKJJJK*^L+"\O+ +M"XMK:VMKZZKJZFJ*BHJ*:BJJJBOK:PLKJZKJ*FIJJBMK"\L+BXMKZRNJ*NKJ +MZNIJ*BHJJJJJZNKJ:BJKJZOK:^NKJROKZ^MK"^NKJZNKJZKJZBJK*JHK*ZHJ +M*VOKJXKJJVJ*JNLK:NN+:^LKZXLKJBN+BRNKJBHJ:HJJZRNJZPLJ"BKJBFJJ +MJJIKJ^HK:^LK"PLK*RNJ*BIJZBHJJZHK*RJKZRLJJZHJZRNJ*XNK*FN+:PL+ +MR[N+*^LKBLKJBKHZ2FHJ:JHKB\O+2PL+"ZLJ*BJKJRLKZXLJ*NNKZHHK*IKZ +MJNK*B@N+*JO+NRLK"\NJZBL+ZVKJ*VL*RHN+JBHKZNHJ:FJJZXK*ZJLJJXM+ +MN[O[2XMKBRL*ZHMKZJIKZRNJJZNK"OI*:FH:^BH*FHHK"FK+RRL+RSM#PXN* +MNXO"XHKJBOO#4^^O8[/3*^+:NK+R6EJ"XN):^OHB(MH"KJXR0J(K>ZLJ,P^C +MZE./.VO;XY._D\.GYQ?YB3NO_T:X.&AH:$82KY_O3Z<?FI9&OC96IH,O+R?' +MA\\[RSOBDLMS3Q^G-T>G7]^Z6V&!)N[YZZ``>,@@&"A;*7^#UXF/EK:2'A8F +M<Y^?SU_'[Y)2ZO+>[BI[8V\G)Y\?9]\B*R-^SFIW03&_-R'K8+`@(+#@*,]I +MMZEY^;,H-D9(^%ZI9]N).0?NP@H&5L8J0UHJIS?_B^^?+UIRRJ(BDO+*V3TM +MH-FM6.PLF$#LH$89X=^YP:'H8`;H@`#6%YF!V5D!MR@(5A@@=HNG]U?)B:=R +M[MJ&5O;.XH+/A^>WJ9EQT2->F49P$*!8P`@N=TGW-^G7ACAVEL@H[ZDWJ6DI +M7RZFIF869GL#NG-G7WOJ6Y/Z[FJ*XBM3_Q,'44UW9G$W\"R`8%``.,_Y-Y=9 +M(</(QO88X&BG%V<)89EOJK,F2(@F_EX:7Y<W?__?8\ZFGJ;^BD,/Y]G-[;9) +M\8@LT-APT""VZ>FW.8$Y-J@>R.!8+A_+QZ&AMS_G"G;H-B8&)NL'1Q_GMW]K +MZX(^$J[.LC>MS;<?K<>PT"!`+$`8NY>G"8%ASUXJ-EC@:#*R2VFA"5\7AR:H +MAE[6-I*#?W]_QX</TYO+.LXRF@^QS4FJK<F`\-@`[+"@A@^OJ2'A1SH/GDB8 +M*%[F(K<)EX>7YS+F#@ZV9B(K.]._/T_O3V^JP@J+KX$-H2L16:`PH(`L<&`H +M"GJ7(>'7_\>2R+A6-JC^7W?'!U>7>YZ"2D8VFJM"(\\3SZ=/+T\O*@)7K2W[ +M.5$;``!XD"RP($8^"HGA&>>W=Z8(*$8H*-)/?Y]'J>>*JX-^EDY*+C*3SQ-/ +MGT<'2N__Q]%M?^FM/P!@^)`LL&#HADY7(1GWJ:FN5A9VB.BFRZ^_MRFW[\_/ +MKL9.[B9N:GIKG]_GMY<7$UF-`>8!P3A`F*"LD(#X1L9C^:'7!XE/-C;F%HC6 +MCGN;$S>IGY-?TQX>\KY^TJ+KVV,G-Q]'"8%ML6<Q(0B`H(#L4+#@");/^:&Y +M2?D'6LZH^/C(Z`8BSQ?IJ2GWT^*N)I8VYGXR(Z?W*6D),8U!UW$A2&"@0.Q0 +M\&`XZ".YV3F9V=?/6Q;X.'CXZ"9B'U?IB6DWWP-NQO9&-D:",Z<I2<&-+1GQ +M\2Y8H(#L[-`P8!A>J9GY68%Y=[=:N/CX(-AHQI*GUXE):1>W#PZ&9G:H!GZK +M!VD!C>UAK1%O*$B`[.PLK#"`Z-_)>6%!X7GY#VB(&`!@&#A6LP?I>?FY2?>+ +M^GYHJ+;6?E^)<8WQ\8T!0^8H,.PL[*S00&ASE_G!08$!(4^FQJ!`@.#@2'Z# +M=TEYV9GIMR>N=K96*"9#(2VQ08V1"<?C&!#0+"PL4(`(/@>A@8&Q\5E/3Y[@ +M`."``/@&8J=IF:%Y24E'JZ+FJ)9F2X%Q27%MH:GI(R!`\*RL+!!@.!9G&:&! +M<3$9B==F&*!@P(#8B&:SE\GY>1FY%X?_SH;./M=Q>>GMP4?IJ19@(/"04%#` +M(!BV=^FY`3%A^?D7A@BX((#@F,CV:H<I"?D922FI)R)*HMHA`2^!45<'Z2^8 +M&.`P,!`P8*#X`D='><$!H7GY9X;6""!@6)@X]OI_]XGY.0F)J:>OXSIIL2EW +M45F/%_?6H/@`0'#P@""@J*^/5R&!(9D9R8->1DB@6)@8R`:2<T=I2;FYR>G' +MY^\?`2$BP;$S)_<B6+C@`$!P@.`@.'ICGWGAX:&9&9<NSG886/@8F*@F[A/W +MZ8G)B0DI9X>?";%7M]%)VS=GZ-BX``#PL&#@H-8K"I>AX:'9H4F_B\Z(F/B8 +M6$@69K+_ERF)R;E)B6>_Z:%9XV$!"X='RI@(&(``L.!@(+@>3C,)F5FAF9D) +MKXL^B#A(F)AHU@;B#P>I:8D)Z:D7)RFQN:]QV:-W!V8XB.#@L+!@@&`(IH:_ +M"7FAV5DA*9_?3@B(R-CXZ"BV@N\G]^D):>EI%U^7@:&+P6&J]X=NN&A8(`"P +MX&#@N,:V2ZFY&7E9(>FW1UJH5FB8^`B(*-YJTP>I:8F)B>E'J8$A$P%A2Y=G +M;LAHH.``,&"`8/B6UKHW:9E9F2%YUZF_!K;6^/C(2&A&GHL?QZF):8EIEP?7 +M(=F;82'J%V>N:*B86&#`(&#@^):H$N<7N9FYH1FIJ<?2YF9H2`B(B*AF4JL/ +M1Y=7:6F7]VGAH?^!X4]WI]N(Z#B@@,`@@&"8*.@^3_<)F3E9(8EI5[/^WJ@( +M"$@(*';>VKNGMQ<IZ2G7J4EA*;<!UV_W#X;65AAX8.`@8"`(:"@:3X<)F4G9 +M&8GI=^-R'M;H:`AH*-9>4CK_!_>I::FI5\EA5Q<!%]\7WR9&UO@X8."@8&#( +M2(C.V[]IN6FAF0E)Z9^S"H8VJ&CHZ"AFIKYSGZ>7J1=7UW?Y6:=)H2?GM]/& +MIBC(^""@6""@"$CH/OOO*2EI&3F)"2G?_QM^YD:HUA96AB;.JZ_/1W<WUZDW +M%_F)OTF)LV]_6K8FJ.A(>/BXF#@H*);.>X/'-Q=I::DIJ><?#XKN#N8&AN8^ +MKK(+[\\?Y^=?Y]]_SP]_']N#SYOB6@K.'AZF!@;&1H:&IGZN,DJ[H_/OCP]/ +M[Z^O4\,#XQL;.\L["ZO+BZH+RXN+.SL[VYN;.[N[JVJ*2AJB(J*B6GKJ*RO[ +M&[N+^XNKZKJZ>N*"HH)"PF+BHOJ*:NJ+RTO;X\/#\W/S,[-#8Z-[N\NJ2KKZ +M6J(BHJ(:2LH*JNOKRSM+RSM+B\N+*RIJ2KHZ^GJ:>GKZNLH*JXMKRPL+2[N[ +M.SL[^TL+B^NJ*NK*2FKJZJKK*ZHK"XMKR_N[BTN+Z^NK*BH*2HJZ.@H*RHHJ +M:BHK:PN+BPMKZ^LK*RN+ZZOJ:NK*"HH*ZNK*BJKJJPM+"\L+*^OK:^LK*^NJ +M*JNKJVO+"\O+BXN+:^LKJZHJ*JHJ*BHJJNJ*:NHJ*NKJBFKJ"HHJ*ZJK:VLK +MJXN+:ROK*BHJ*HJ*ZJNJ*[L[R[N[^SM+"PMK*RLJBFJ*"FIJ:JJJ*BHJ*FKJ +M*BJJ*NJJJRLKZ^LK*RNK*BKJ:@IJ*JJJ*VMK:PM+2TM+"VN+ZZLJ:HJ*B@IJ +M:FHJZBJJBFJJJBJJJZOK:PO+2TM+RXMKJ^J*"@K*BNHJ*JLKZRNK*ZNKZRNK +MJZNJ*JNJ*JNJJJNJJZOK*RNK*BJKJJJKJROKZ^OKZROK*RLKZRNKZFJK*HHJ +M*JHKZVL+RVLKJNKJZNKJ*NKJZNKJ:FJJZ^OK:XMKBPOKZ^OK:VMK:^OK:ZNJ +MZHJ*"LH*ZFIJ*JNJZ^LKZ^MKZROKZ^OK:VOKJZHJJHJ*JNKJZHIJZBJJJRNK +MJRLKJBN+B\O+"VOKZ^LKJZJKJZLK*RLKJBNJ*NIJZBKJ*FJ*ZBHJJJJKJNMK +MZXN+Z^NKZNIJZNIJZBJKJRMKBVMK"XLK:VMKBXMKZZNK*NHJJNHJ*NIJBFIJ +MZBHJJBJJJROK*RLK*ZLKZRNKJRNK*RNK*ZNKJZNK*ROKZRLKJZHJ*BKJ*JHK +MJ^OKZ^OK:^MK:ROJZBIJ:BKJ*JNK*ZHKZZNJ*FH*RHKJJBOKBPO+R\L+"PMK +M*RKJ:HJ**J/S+H(+,J-BNZMJRVI[:FLKRPM+:[N+2ZKKJXIJ*HHJ2JIJ:BMJ +MBVN;:PN[ZXOJJBLK:HKJRHK*BNJJJBHKJBNKJPL+JROJ*ZHJZRMKJHLK*ZJJ +M*JLJ*FKJJPJ*JBKKB^L;JSNK2VMK2PJ+R@N*JHKK*BIJ:RNZNX.GVWZF?NZ" +M6H/#FX,SCZH;R_O;>S.Z9T-FVHZ"XM)C+EN2"S-BXSLC2QNK6ZH#FBK#^B/2 +MJVL2HS(+F@JKFF-B^WIC.MO:#^[_CI/ZX[IZ$[(3#@_2KVY/KM.BNSHJ6U+_ +M`X>.KF9^YHY:FT]2AS,O4XLO&WO*ZGLK#DL:Z@HZJON2ZR+;&U)[B[L**RI# +MRIN*HQOBBNIZFQJ+JWJC^MK;VN,Z\_O3(RJJGEJFDH)[BJ]#KV^CKQL[FR++ +M.NNBVH++F@*;[INBRPI;BPOJLVL;,WJ#ZHOZBQJN6P([$J/:"CO:`[HKNK,C +MVBM*"PI[&PMKRH([8ZO[<N,ZP[J*[U+:.HKS^BI+N\..F@K[FK(#BB/[LO.* +M<V[3KRJ;+GNB2U+*VRKKTI-[DUH+6[MZ"H)+ZDLR2[.N:S*;.WI+FL_"&LOJ +M+\**FSM;KHK3BS/";WL*&OI+NG(B&VJ2&WIOVJHZ2X.BBBK;(DN"$TI**UMO +M>@,*DVL+0H(C#J("^XMB^R);BPI*K\ORL[I#XDLZ._.K*OH/<KLBZZJJJ_*O +M2G.""GLNPU)[VI.*[H\;BZ*/3JM#PF(C\PX[$\+[<PJ"JXH.+PN:@E/:$M/K +MJWN_:F-SPKOK6@ZC2S(C*L(K2AX#[RJ:[XN::KY+CZ^2^L][@AHJ(PLB2J-C +MVZZ;B[LRSB,"+Y)J*N-:\DN##TI+ZK.*KEL;&UIZN^N+*ZK[$DL"NJ(JDZHR +MV]NJ.H(;BH]Z"V/O:\+CXT+B*AO;@HZ:LZH.FO,;&V);2]LB?H_KFTYK>UM3 +M8D-SPZMZ"]JKSJX[SVKB.[/;@NHZ#WKJKCI#&KK:XX,2@KNOBSK",RK[,KKS +M"GMZ#WI[XM*J.@O:.SM+NDLK6\N;@NK[^HL+:J.+:N+*"YKCVEMJ+^J:RZ*C +M;KI..LK"LZO_.CMCLX,*^FNSHK+;0[LKJAJ;JF+ZZ\ORZDMC.SNZ*FLZHE)[ +MRHJR`],*:ZM;*OLJ*DO+*UJS>FIK>@+ZNYJ*JAM+,TK;,^O:8JNB*DM+H^K: +M^BN#J]M["IMK.T*:&B(+ZBJ*`ZOJXR-KZBJ"JPMRPBM+NEO;&[.C:^KC@OKJ +M:VMJZJX*"OH+RWN*>YH+(YLK&BK:2RJ*:N.;"NJJ2RJKR@LK*N)*"VIJ"LIK +M^VNKRR-KJ\KJZBJKJ^,;&PM[.SNKVGK"HD+:.NM+J^K+@[L;2SM+*LHZNRN: +M6HJKRXMJ^]N[RBKJ*[N*@C)*^HJJ:TO[2PL#LYM*FKK*6N*ZV\-C2PL[*CK: +M"FKJ"LHJ*RNKFX/;J^OJ"@HZZBJ+:NJ*^@I**NN[N[M+JHKZ"@KJBWNCH_M+ +MZVMKJ\I*2KJZ6B(ZJPL+N_L[NVNK2@JJ:NJ*"@K*ZNH+"WO;6_O+RVKJ^GK* +MZJJJBWL[ZVM+"^K*NGHZNCI*JJMKJNHKJ\L+FUN;2RLJRGJ"VCHJ:\L;>]L[ +M"^NKZDIJZNKJJRLJ*ROKJJJKJFJK"^OJBJHJJJJ*2KJJZFJ+^SO+2XN+BZN* +M*NLJBHIKRSO+:VL+B\KZFKKZ.NHJBTL+ZZJJ*BJK2PL+*PN[ZVI*RNJK*HJJ +M2SNJRLHK"ZH*NJN[RZJJ.WN+:@HJ"PNK*JOKJHJZNCJZRKIJ*JNKZ\L[VTLK +M*JKJ.OKZ*KL;.SN;>SO[RZLKJVKZ>CI**BJJJNHJ:JHK:^LK*RNJ"HJK*^OK +M*RMKBVL+NVNJB@K*2@I**NMKR\N+*JHK:^JZR@HJ*JHKZXL+.TL+BXMKZVLK +MJRJJJZNK*HIJ*NH*2LH*ZFLJ2BI+NVLK:^MKJRIKBXNKJBOJ:NJJJBLKJBOK +M:VNJ:FHJ:@J*BBJJJRNJJZOK:^MK*ROK*^OK:^MKZ^HJJZJKJJNK*ROJJJN* +MBJHK*JIK*RN+"XMK:^NKZ@KJ:HKJJRIJ*NJKBXL+R[O+NSMK:FIJR@H*RNHK +M*ZOKZZJKJZHK:^LJZBJ*"HK*2FHJ*PL+BTO[NPO+B\N[BRIJZHJ*"KJZZJJJ +MJHN+BRNJJJKJBFHJ*JKJ:NHKBVN+"PN[2\L[N\L+JXI*RLKZNHHJJRLKJ^OK +MJRNK*NJJ*^LKJBJJJBJJ*^L+2XMKZRNJJBNKJZLJZFH*R@IJ:JIK"PN+"XO+ +MR^LKJZNKJRHJJBHJJZHJ:KI*ZJJKZXLK*VNJZBLK*JLKJRLKJBL+B\N[RPN+ +M*RKJ"@H*2DI*2HHJJRN+BXN+:^LK*RLKJROK:ZNKZ^LK*ZNK*BKJZNHJJBKJ +MJJKJZBHJ:XMK"XOKJZNK*JJKJNOKJZHK*RHJ*^LKZ^NK*ZNJZNKJZJJKJROK +MBXLKJJHJZHIJZHKJ:NHJJ^OK*^MK:^LK*VMK:^MK*ZNKZBJJJ^LK*ZMJ*NIJ +M:FIJZNJJJBMKJZHKJZJK*ZNKJZJJ*ZOKRTL+R\L+BVLKJBHJZBIJ:BH*"BHJ +M:HIJ"HIJ*BJJ*BIK"\O+RTN[RVLK*RMKZRLKJBJJ*^NJZBIJ"HJ*"@J*:NHJ +M*ZOKBXMKZ^OKJ^MKBXMKBPL+B^NK:HIJ:HH*BFHJ*JJJ*JJK*BJJJJJK:VN+ +M"PL+:RNK*NKJ:NKJZBJKJJJK*^LK:BKKJZLJZBKK:^L+2XN+:ZLJJ^KJ*FJ* +M:FIJ*JHJ*BHJJJJKZVN+"PN+"XMK:VMKJROKJZKJZFIJB@H*"HIJB@KJ*JHK +M*^OK:VN+"\L+:PN[BROKZ^OK*RKJ*JHJZFKJ*JHJJJNJZFJ*B@J*JBOK:PO+ +MBXMK*ZNJ*NIJZJJJJRMK:RMK:RNKJZNJJ^MK"\N+BVNKJNJ*B@J*BFKJZJNK +MZFJJJZHK*ZOK:VLK*VN+B^NKJZLKJZNK*ROK*ZOJ*JJJ*BJK*ZLK*ZJJZXNK +MJZNJ*BJJJJLK*ZNK*ROKJZOK*RNK*ZNK*ZLJ*NIJ:HIJZJOK:ROK"VOK*ROK +M:XMKZZNK*RJJJZJJ*FJ*BHH*B@J*ZNHJJ^N+2[L[.TO+"VMKJ^HJ*HH*BNJJ +MJJHJJNJ*BFKJJROK:PMK:PN+:PN+Z^NJZHK*:NIJ*JJJJJJJJBNKJRNK*^OK +M*ZNKJJHJ*JLK*RLKZ^LKJZNJJBHJ*BJJJZNKJJOK*ZJJJZHJ*BKJ*JJJJJJK +M:VMKZ^N+:^OKZRNJJJHJJVOK*ZLJJBIJ:HH*ZBJJJZJKZ^LKJZNK*VOKBXLK +MJZKJ:HIJ*BIJZJHJ*JOKZ^NKJROKZVN+BPL+BXMK*ZJJZNIJ:NKJ*BKJJJNJ +M*JLK*RNJ:JKK*VMK:XMK:^NJJBNK*BHKJJJKJBJJJJNJZNJJ*NKJ*BJJJBMK +MZ^OK*^OKJZJJ*RLKZRNJJZHJ*^MK*ZLJJJLJZBHJJJNKJ^N+"VLKJNO+:ROK +MJ^OK*ZHJ*JNJJZHJZ@I*"HKJJJLK*^MKZROK:PO+2\N+:ROJ:FJ*RLH*BNJK +MJJJK*ZLK*ZNKJZNK*ROK:PL+"^OKJRNK*ZLJ:NIJRDKJZFJJJBJKJZOKJZJK +M*ZLKZVN+"XMK:VN+:ZOJZBHJJJHJ*BHJJJNJJBJJJRKJ*BJK*ZJJJ^LKZ^OK +MZ^NKJBKJ:NJJJZJJJBJJZBJKJJIK2XN+"VLKZRLK*RLK*ZLKZ^MKZZNJJJIJ +MBHH*BHJ*:NHJJJOK"TM+"PMKZ^LKJZLJZFIJZNJJ*^OK*RNKJJJJ*FIJ*JNK +M*^MKBVOK*ZJKZRJ**BKJJJNJJRLK*VMKZ^LKJZHJ*BHJJZOK*^OK*^OK*RNK +MJBHJ*FJ*BHIJ:FIJZBJKZVMK:VLK*^OK*ZLK*RLKZ^OK:XMK:^LK*ZJ*BHJ* +M*NNKJJHJJJNKJJJJ*NKJ*JJKZVMK"TM+RXN+:RNJZNKJ*NIJ:FIJZNHJJJLK +MZRNK*RLKJROK:XMK:^LKZ^NKJJJJJJJK*RNKZFKJ*NJ*"FH*2NHJJVMKBPN+ +MBPL+BVMK*^LKJRHJJJJJJZLKZZKJZBJJJZNKJRLK*ROKZ^LKJZJJ*BJJJBJJ +MJRLK*ZNJ*BJJJJNKJRNKJZLK*^OKZ^OKJRMKJJJJZBJJJZNKJZNJJJJJJBJK +M*ZNKJJNKJJNJJVLK:XNK*NMKJRL+ZRJ*ZJMJ:NHJ:BJK*JKKZRNK*FKJJJNK +MJVN+BXL+R\O+B^NJZNIJ2OH*RLKJJZOKBPN+ZRJJJJNKZVMK:VOKJZJJJJNK +M*JHJ:HJ*:NKJ*BJKJZOK:VMK:^NKJZNK*JJJJJNK*RLKJZHJZFKJZJJJ*JLK +M*ZLKJVN+2VLK:RNKJJJJ*JJJ*BKJZBHJ*JJK*ZNK*ROKZ^OK*ZNK*RLKZ^NK +MJJKJ*JJKJZJJJJJJ*JHKZXN+BXN+:RLJJBKJ:NIJ:NJJJRMKB\L+BZKJJRLK +MZZNJJBHJJJNKJRNJ*NIJ:NHJJJJK*RLKZ^MK:VOKZZNJJJJJ*JJKJZNKJJNJ +MJJHJJJNJ*BHJZBJKZ^MK:^OK:VMKZZNK*RLK*ZLJJ^LJJJLJJJNJJNKJ*FKJ +M*BJJZVOK*ZNKJJLKZVOKZ^OKZRLK*ZNK*RLK*ZNJ*BJJJJJJ*NIJ*BHJJJJJ +MJJNKJZHJ*JJJJJJJJ^OK*^OKZ^NJ:JHJZJHK:XN+:XL+"XMKZRNKJRJJZBJJ +M*BKJZFJ*"HKJJRMK:^LKJROK:VL+"XOKJNKJ:NHJJRNK*RLJZBHJ*NIJ:BHJ +MJJLK*VL+BVMKZXO+*^MK*RLK*ZNJ*JJJ*BJJJJNJJJNJ*JNJ*BHJJJOKBVMK +MZRNKZFJ*:NHJJBLK*RNKJRLKJZLKJ^NKJJNJJJJJJZLKZVL+B^NKJBKJZJJK +MZHJJJBJKZ^OK*ZLJZBJJ*FIJZBHJJ^MK"TM+RPN+ZZKJBHKJZNIJ:HKJZJJJ +MJJOKBXN+BXOK*ROK:^OKZRLJ*NKJ*NKJ:FKJ*JHJ*JJJ*NHKBROK:^LK*RNK +MJZLK*RNJ*NHJ*BHKJJHJ*JLK:XL+"VOKJBKJJROK*ZHJ:FHJJJNKJ^MK:^OK +M*ROK*ZNJJJHJ*NHJ*BIJ*JLKJ^OK*RNKJ^J*JJHJJBJJJRLKZVMK:VN+:^LK +MJJKJ:FIJ*JJKZXL+"\L+BVNKJBIJ"@H*BNKJJJNKJ^OK*ZNJ*JHJZFKJ*JHK +M:XL+"\L+B^NKJZNKJZLJ*VNJ*NJ*BHJ*ZBHJ*BJJ*ROKZXMKZ^LKZRLKZRLK +MJZNJJRNJJBOK*ROK*ZNJJBKJ*NHJ*BHJJJNK*^OKZ^OK*^OKJJHKJZJJJRLK +MZRNKZVNKJNLKJJJK*BHJ*NKJ*NKJ*JHK:XL+"^NKJHH*RDH*:JHKZ^N+"PN+ +MBVOKJZNK*RNK*BJKJZHJJJNK*RLKJZJJJJJJ*JJK*^MK:^OK*RNKJBMKJJLK +MJJJK*NIJ:NKJZBHJZJJKJJJJJJMK:PL+:^MKZ^MK:^LKJZKJZHH*BFKJZBJJ +MJJLKZVN+B^NJZNHJJJOKBXL+BVMKZZNJJJHJ*BKJBHJJ*BJKZRNKJRNKJBJJ +M*JJJJJJJJZNJJZLKZVMK*ZNK*JJJJNHJZFKJ*BHJ*JNKJRMK:VMKZRLKZVMK +MZ^LKJZNKJZJJ*BKJZNKJ*FJ*"HJKBVL+2PN+:^OK*ROK*ZLJJJJKJJJJJBHJ +MZNIJZFKJJJHKZROK:^OKZ^OKZRLKJRHJZBJJJZNK*RNKJZNJJBLKZ^OKJZNK +MJZNKJVMK:VOKZRJ*ZHJ*:FJJ*NHJ*JJJ*ROK:^MK*ZJJJZJK*RLKZROKZROK +MZVOKZRNKJNKJZNHJZNKJZJHKJZJJJJLJ*NHJ*JHKZXN+"\O+RXLKJJHJ*NJ* +M*JOJ*BNKJZNJJJJKJZLKJZLK*ZNK*ZNJJJJKJRLKJZHJ*BHJ*JKK:XMKZXMK +M*ZLK*ZJKJZOK*^OK*ZJK*ZNKJJHJ*BHJJJJKJZJJJRLK*VNK*BNJJZNKJZJJ +M*NHJZFKJ*BMKBPN+BXOK*ZHJZNIJ:NHJJRNKZ^MKBPL+BVMKZZNJZFIJ:BJK +MJZLK*RLKJZJJZFJ*:HJ*:BJJ*^OKZ^MKB\M+Z^N+*ZNJJJHJJZNJJ^HJ*NHJ +M*JNKJZNJ*BOK:XN+BVMK:RLKJZNKJBJJJJHJZBJJJZNKJJLKJZLJZNHJ*JJK +MZVN+"XN+:RNKJRKJ:NHJB@HJ*JHKZVMK:VMK*ZLKJJJK*ZNKJZNK*RNKJBHJ +MZFIJ:FIJBNHJ*^OKBXO+2PL+BRNKJZJJJJJJ*ZJJJBJJJZHJZNKJZBJJJJNJ +MJJHJZNIK"VN+"XN+:RNK*NKJ:NJJJJLKZZNJ*BHJ*JJK*ZNJ*FHJ*JHK*VMK +MBXOK:VMK:^LKJBKJ:NHJ*JJKJZNKJJHJ*BJJJZNKZ^OK*^MKZVOKZRJ**NIJ +M*BHK:XN+:RNJJJNJJBKJZBJJJ^LK*RNJZFKJZNHJJRLKJJJJ*BHJ*BOKZXN+ +M"\N+BVOK*ZNK*NHJZNJJJJJJJJNKZVMK*ZNKJFJ*JJIJ:BJJJJLKZVOKZZNK +MJNIJZNHJJROKBXN+BVMK:^OKZ^NJ*NKJBHJ*"FKJJBMKZRNKJJJK*VMKZ^LK +M*RLK*^N+:RNJZFKJZNHJ*JJJJJIJ:BLK:XMKZROK:XN+BXOK*ZIJBHJ*:FIJ +MZJJJJJJJJJNK*ZNJJROK:XMKZRNJ*JNJ*BHJ*BHJJJLK:^NKJZHJJJJKZRNK +MJZNK*^MK"PMKZXMKZFIJBFIJBFIJJJKKBPO+"PMK*ZLJ*BKJZNKJZNHJJJOK +M:VMK*ZJK*NKJZNKJJJJKJZNJJJJJJZLKZXN+BPL+BXMKJ^IJ*BJJ*RNKZFKJ +MR@JK*VL+"XMK:VMKZZOJ"DJZ2KH*ZFIJ*BNKJVL+NSL+2[N["XOKJNIJJJJJ +M*VN+*PMKJRJ*"@I*"GI:.JH#T[*N4R/&2`K70S_'Q_NO([:&#SE7:%CV2<DR +M^(A/7T<"KV.V=B8WZ2F'!D9+CR;H:#['*8GG(HI/O^J.#N[+LP..1O9FFML_ +MYP<3'L;.\Z]+(AN'QR>_\QM[\@:HMKHZSAY+9W>#0G-*OZ?#/F8Z@X_K2]N; +MPB9^2M_ONJ8&>E,'+\N[:I^;6S)^LU-3>L**CJOKOM+N2SNZD\._,S-#B_-* +M6GZF$LJC>GJ;`Z_S@ZL:*@L[#L[JDW.;*DI3+[.ZLCIZ:YK.;G*B\_\?GSMR +M+OK;XA)Z2^N*"W+Z+P_3J])JR\+RKC,C`^MR8YN_D^I[LD.:3@Y2\RJ+"^L; +M*N/K>J*RBAN["JHK"BISPR/KVCM+.POZ.EH*RIH2B_-[RHJC2UOK,D(ZHUL* +MV@)*\].C2XMSXYK"\C):&JL;8\/CV[M;*T(:&LKZHO)"HY,C^WN[NJN;&[MB +M<@IKJNH:N[/;NUI*NZKZ,B(+@^/B0HIC[ULJDGIKHYM:@GI+`UNKJ_O;.^H: +M2DKZ>HO;,SOJ*_KJZ\HBPOM+&DHKPUL*BAI*NZN[*[M+>VLZ"CIK2RKZNNNJ +MBRI*>@J;(UNKBHMJ2HI*.FK[,SMZFNJC^TJRFIN#8VO*RFH+"HO*.J+*ZRN+ +MBFO;&]N;^VL*&A*R>LN+JJJ+F_L["^OZ&BJKJPM[&YN*JDO+*\H*FAKB&IKZ +MBWM;.RL+HPNK^J+*JLLK:[NC&XOK"FJ*N@J**JL*:JO+ZZKK2UNKZ@H*:NK+ +M:XMKBDIKRZKJRKIJBZMK.UO;JAJZJDM[*@JKBRK*ZFKJRIKJBBHKJPMKR_M[ +MN_NK"FHKZCJZ2CK**FMKJBJJZXN+BXL+RPOKZ[O["RH*:N*.KH)ZZHL[VZ,C +MXR,C6]M[^[O+BVLKJBKJ:HH*"LK*RLK*R@H*"HJ*:NKJ*BJJJZLK*RLKZ^OK +MZ^OKZ^OKZ^LK*RLK*RLK*ZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJ_______________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +:____________________________________ +` +end diff --git a/share/isdn/9.g711a.uu b/share/isdn/9.g711a.uu new file mode 100644 index 0000000..7765d02 --- /dev/null +++ b/share/isdn/9.g711a.uu @@ -0,0 +1,231 @@ +begin 644 9.g711a +MZBHJ*JNKJZNKJZHK*RLJ:NJJ*^N+"RNKZZJJJ^JJ*VMKJRIJ:JJKZRNKZHIJ +MZBJJJZJJZFIK^RLZRJHJJBN+NWO[NPLKBPN+ZZLJZNH*RLJ*ZBHJJJHJZBHJ +MJJLKZ^NJ*JJJ*VMKRTL+"XOKZRNKJ^J*2KJZ2@J*ZBJJ*JNKZXN+BXN+BXN+ +MZVN+:VOK*ZNJ*BHJZFIJZNHJJJJJ*JHKZVN+BXMK:^LK*ZNJZFKJZNKJJJLK +M:^OJ:JNKJJHJ*JHK*ZJJ*JHK*^MKBVMK:^LKJZHJ:NKJ*NHJJJJJJJJJJBNK +MJRKJ*JNKJZLKZROK:^OKZVLKJZJJJZNKZ^MK*ZNKJZJJJBHJJHMKJ^OKZ^LK +MJZJJJZJJ*BKJZNKJZNKJ*JJJJJHJ*JJKZVOK:RNKJBJJJBOKZXN+:^MKZZNK +M*BHJZNHJZNKJZNHJJNL+"\O+RPMKZRNJ*BHJRLKJ:BJKJZLK*RNKJNJ*:NHJ +MJBOKBPN+"PMK*ZNJ*BHJ*BHJ*BHJJBHJJJJJJBJJ*JLK*^N+"XMK:XOK*ZNJ +MJBHJ*JJJZFHJ*JJJJJJJJRL+BROKJRJJZBJJ*RNK*^MKBVN+*RNJJRNK*BJJ +MJBKJ:FIJ*JNK*RLKJBHJ*NHJ*VOKZ^OK:XL+BVLK*NKJ:NIJ*NJJJJNKJZNK +MJRLK*ZJKJ^JJZROKBVOK:^MK:^OK*ZNJJJLJZNKJZFHJJJJK*RLK*^LKJZHJ +M*JLKJRLK*^OK*ZNKJZNJJJNKJZJJJRHJZBJJ*JJJJJNKZRLKZROKZVMK"VNJ +MJBHJJJJKJRLKJRKJ*BHJJJJJJBNKJZNJJRMK:^OK:VN+:^LKZRNKJBHJ*NKJ +MZNJ*BFKJ*BHJJBOKBPO+R\L+B^LKJZNKJZNJZBJJJRI*"FH*BFJ*:BHKZXL+ +M"PL+BVMKZZNKJZNKJZJJJNIJZNKJJJJJ*RLKZ^OK*RLKJZNKJZJJJZJKZRLK +MJZHJZNKJZNKJ*BOKZ^MK:VN+:^NKJBLJBBHJ*JJJJBHJ*BJKJJLK*ZLKZVOK +MZROKZRLKZRLK*RNKJRKJ:FIJ*JJKBPL+:^LKJZKJZHJ*:NHJ*NHJJ^MK"PMK +M*RNKJJNKJZNK*^LKZJOKJJNKJJNKJJNJJJJKJJHJ*BJJJ^MKZ^OK*ZNJ*NHJ +M*JJJJJLKJZNKJJJJJJNKJZNKJZNKJJLKZ^OKZRLK*ZLK*^OKZROKZ^MK*ZNK +M*BHKJHIJ:FIJ:FIJ:NHJJVN+R\N+*ZNK*RNKJZLK*^MK:VLKJJKJZFIJ:NJJ +M*JJK*^MK:VMKBPO+"XOK*ZNJ*BKJZFIJ:NKJZBHJJZHJJZLK*@HJJRMK:XN+ +MR\O+"VOKJBKJ:HH*BNKJ*JJJJJJJJZLKZRNJJRKJ*JNK*^N+:VMKBVOKJZNJ +M*NJ*"HIJ*BJKZ^LK*RLKJZNKJZNKZXN+RVN+2PLKJRHJZFIJZBHJZNKJJJNJ +MJZNKJZNK*^OK*RNKJBJJJROKZ^OK:^NKJBJJZNHJ*BKJ*JHJJJNKJJOKZVMK +M:VLKJRHJ*BJJJJNKJROK:^NJJRLJ*BKJ*BHJJZJJJ^OKZVOKZ^OK*ZNKJRJJ +MJJLKZRNKJJJJJZNKJRKJZBHJJBLKJZNK*RLKJZNJJJNKJJJJJJHJ*JJJJJNK +MJZJKZRNJZ[L+BXNKJJJKJZNKJBHJJJJKJBJJ*BHJJJNKJZJJJZJJ*ZNKJJJK +MJJNK*VMKZ^LK*RNKJZNKJBHJZNHJ:NJK*^OK:VOKZRNKJJNKJRLK*^NKZJJK +M*BJJ*NHJJJHJZBJK*ZNJ*^OK:^MK:XN+:^LKJJHJ*JJJJBKJB@J*BNJKJRLK +M*RNJJBJJJROK:VOKZROKZROK*^LK*ZNKJZHJZFIJ:NJK*NJKJJOKZRNKJZLK +MZVN+:^MK:VNK*NKJZBJJJZHKZ^MKZ^LKJJHJZFIJZNHJJBMKBPL+B^NJ*BKJ +MZNHJJBJJJBHJJRLK:VOK*RNJ*ROKJXJJJNHJJRLKJZNJJJJJJZNK*^OKJZJK +M*^MK:^LK*RNKJZNKJBHJZBKJ*BHJ*JJKZVMK:VMK*ZNKJBKJZBHJ*JJJJBJJ +MJZJJJJLK*^MKZ^N+2VOKZZHJZNKJ:HJ*BHJ*ZNHJ*VL+RPN+:^LKJZHJJJLK +MZVL+"XMKZZIJBFKJZBJKJZNJJRLK*ROK*ZNJ*BHJJJJJJJNKJZJJJRLK*ZNJ +MJ^J*JJLJJRLK*ZNKJZJJ*ROK*ZLK*RNJ*NHJ*NKJJJJJJJLK*^OKZZNJJBJJ +MJJJKJRNKJRMKBPO+RPOKJZHJ:FHJ*JHK*RLKJBKJ:FJ*BHJ*JFOK:PL+R\MK +MJRHJ*BHJ*JHJJJJJJZJJJZNKJZLK*RNKJJNJJZLK*RLK*VOKZ^LK*RNK*BKJ +M:BHJ*BJJJJJKJRLK:VMKZROKZRNKJBHJJBOJ"NKJZBJJJJOK:^OK*ZHK*ROK +MZ^OKZZLJJBKJ*BJJJJJJJBNKJ^LKJZNKJZLKJZNKJZJK*^LK*RLK*ZHJ*JJK +MJRLK*ZNKJ^LK*RNKJBKJ:JKK*BHJ*JJJZBHJJZLKZ^LKJROKZRMK:^NKJJHJ +M*BHJJRLK*ZNJJBHJ*NKJ:BHJJRLK:XN+:RLKJZNJ*BHJ*NHJJJNK*RNKJZJJ +MJJJJJROKJRKKZ^MK:XN+:RNKJNJ*BHIJ:BJJ*ZLKZ^OK*ZNK*VOKJRHJJRKJ +M*BJKJZNKJZJJJZNKJJJK*ZLK*ZNKJZNKJJNK*^NKJZHJJJOK:VN+:RMKBZLK +MJZNKJBKJ:FKJ:HJ*ZBHJJJHJJNN+"PN+:^LK*ZLKZVN+BXNK*NJ*RLK*BHKJ +MZBHJJJLKJRLK*ROK:VMK"XN+BVLKJZJJZBHJZBJJJPI*BNJJJ^MKZVMK:^OK +M:VL+RXMK*ZNK*FIJ:NKJZBJJJRNKJZHJ*BIJZJJJ*JNJ*^OK:XN+ZRLKJZNK +M*ZNKJRHJ*FIJZJJKJ^MKB^LKJRIJJRLJJZNKZ^LKJZNKJJLJ*BKJ*NHJ*BHJ +MJJJJJBOK:XL+"\L+BVMKZ^OKZRLKJZJJJZNJZNKJ:NIJZNIJ:HIJ:JJKJBOK +MZ^OK:^N+BXMKZROJZNNJ*BJJ*NKJJJHJJROKBXN+RTO+BVLKJZHJJRNJZBJJ +M*FIJ:FKJZFIJ:HJ*B@J*ZBJJZVN+BVOKZ^LK*RLKZXN+B\O+"\L+"PO+RPMK +MBTN+JZNJJJNJZBKJ:FJ*2KHZ.OIZ&J):6EK:&OI*"FJJ*^MK2SL[>YO;HV.# +M@P-#P\-#`Z,;F[L+NYL[.QN;^[MKRAJ"DN[./GZ>'AZ>_@ZN<N(*:WMC0W/3 +M+V^/#P^/;^\OKU,3\Y-S`^.CNPNCT^]S0Z^C"MKNIN8FAL8&1K8&YB;^DLI; +MKX]/?W__'Z=?7^>G?\\OPYL+JZOJNMJ"$JZN[HXNKBZNKN[NKO(BRFO;LQ/O +M#P\_I^<G9X>G_\\#BJ)2/MZFA@8&Q@;F'K[N(DHJB\L+N_N;HV,#PW/3KV\/ +M3S^_3P]OKS.#HSLJZ^__X^,?+^N;:CZ>/H9&AK:6M@8&)KZNRJ/S;_]__Z?? +MOW\_KW.3H_NCFPN;&RNK:VJZ^J+"PC)24E+2PJ+:2J,?!Q]G5T=?IT\J^J+> +MYJ;&EO;V]@:FSMI+6]-ODX,#HUM#8]O#\X-CXUN#T].3<Y/S(^O*2KH*"IH* +MSV=#4S<G\\]S<G+"9D;FMI:VMO9F/F[Z6_.//\^/;S/C,\-;(R-;8X,[>T,S +M,[,#8]O+ZIJ"@F("8N)[YU_CQQ???]][`NKNQF:&EI;V%G9F'J[J>]-/#V]/ +M4UM#$P.S\Z.#$T.;6^-C`X,C&POJFH)"@F+B^L-'A[/'U^???[K^DCXV-I8H +MU@9FI@Y"(]\?CR\#ZCI"'MZNHBHS+T_GQ\<'IP]SXVIRSAY>OA+:V[>9(?E' +MA^>KGJB8H#@(""B69CL'-^??GV?G^][&AIYNSKXB#\?WMP<'!Z=;KM[F9B9^ +MC@+K0P]?Y^<I84%9I]XF]NCX("!(YHXN\DJ_E[<#?B8N&OZ6EHX/Q^>O0Y^' +MI]-K:\/#&K[>#IJ;`^-S_Z>G?[?A<8$7QNBH:#C@8)AFJLJR[@L'=Z]FJ$9J +M+])&'D^IJ?]",O/?CRKB.T^/"KX>TCLSVPN#[[\GR3%1@:=H.+BX>.#@2"XO +M@YINRV?'JQ8(5KH_*MZNIVGI;UXFBA^GLSH+CP]+CJ:.2P^_\ZHK$_?AK5&9 +MIMC8>+B8(-C60Z>3\MY*7W\.:$A&SR=KCJO'*7?*-D;B'V?_PR-S\ZN._@*O +M7T\#@],70>U1:<@`8!AHR%@8-D^W7W(&#D\?+FC(AA/?,PLO!W>GTO9&0O_' +M9X]+BMJ"$I(JKY\??X^?>:UM04I@,("X]F@82*:G]W^>UJ8[(QXHJ*;JTS]G +MQ\??ZEZ&?BM?-\?/2@[.LFMS#T^_GY_7L6VM"3@PL""6YLAXB'+'UW^&5N:B +MVN:6MIY*#[?7MW\*IH:>^F_GQR?3HCZ^HN-_IT^S<P?A[6UA-C!P`&@"QKAX +MUO-7J2L6J`:N[B8&9CZ*IU=79[M>QEZZ;R<')R^*CD[RNT_G9W^O9V'M[>&H +M<!#`UA.2:'AH@A=I[T;HJ&8N>B+>MN:O*6G'6G86/B^'1R?S:B(24EK;OX<W +MAX<9K6TQ"T!0<)C++R;(N/;3Z9>*]HCHMH+[4K;6$G=)B5.6R!;[EXFI#S)N +M$B*JVZ]?!\='F='M\0^`4!"@PH_2*,A6ZBFICQ[HB*C^:]IFUD['R0D_]CAH +M@C<)Z1^R3O*+;P\OOZ?'";'M4?G(\!#`5FM:]@@H?N>IYQI&J*@&8K+&*#9O +MB;D7+HA(Q@_IB;<[/CZ:+U]_S_]G27%M46E8T-"`7G^:J#AHKE>)Y^[6*):^ +M"GZHB&8'.3D'QOBX)B>)Z1\27NX;)\=GIQ^WH:UM,?/`4)!8>L_.B#BH>VEI +MGSZHZ$9:\A:X"%J)H3GS:!B(:BFYUXK&1I+_]S=?OX>948W1!X"LT"!Z9V*( +MF&CK"3G'ONB(-LH*EGB8WFDAV9]HH+BRZ7EIFT9V#@_WE^?/IWFM#5'W@*Q0 +M(/IG0DB@R`I)>7=N:,B6>@NV^'BF*:'9?X@@.+(I^>ECAC:./U>IAR\?62V- +M<7NP+!`X/V>FF""([_DY!QYHB&8[,N@82#LYX;FB^*!H,XFYMS)&YFO'*9>G +MC_?!;>TAB)!0`&;GH^B@F&:7^2EKEBC&FJ(H6-B&Z>&AYRA8.*Z7"==;GEY* +M7Q<79Y^W(2UM0<XPK+#HWT]VH*!67SD);X:H!KKJUJ`@J'<A(9>6V#@^]PE7 +M8Z;F6J?7J0<_IWE1C9&/0*SPR#^GQE@@Z,])"2^&J&:+,T:@@,AG(6'I!ACX +MWL?I=QN>_NH?MW?'YS=9K8UQ&["L,(A_[Z@@H/;G2:DZ-O:N;[MH@("H*6$A +M1U:8"`)'EU\K<CJOI^=G9P?765%M,=O`$,!HD^N((-CF!PF7LL8F"@^:2,"` +M%NGAH:=6N%;*YX?/.ZJ;$^^_9Y?IR6$M[6$V,'!@MO->>.!(FI?IO_Y>.D_S +MMB#`6)HYH6FZUE8^P[_OLT-#(^OJK_<)23G!+:TY2/"PV*;*J*"@UH\7-PH> +MVO^'HCC``*@WF4E_'D;^^BJJ&W]G3VJN^J?IN4G9$6TQRP!P8%8J)IC@N/I' +M1UM>DC\'KZC@P)@KB<FWZCY.$M+RR]^WYSO.#J\I.;F)82TM>4CP0#B^<L@@ +MV.;GQ_-^OK_WAZ:@P*!>-^DW$ZLJHGZ&;L_W-V-^7@N72;D)&5%M01Y`,!C& +MKN@@6#;_)VJ>OA]7!XZ8@"`6[P=GG[_/ZB:6)D_7%S,>'HM'Z6DIR?$-K>=@ +M,-@V)FC@H+8_G_Y&SF>)!T[(H!B(IKL_1_=G:^8VIL-'MY\ZCM)#]VEI::$M +MC6&6P&#H]NB@X(AJWR(VGO]I5UI6.'BXZ%Z[A]<W#RYF)G(O)R<OND**_Q=I +MB4FQC:UG6&!(%H@88/B.+\IVQJ\IZ0-&J,CX."AR7Q>7IR,2?OYB+R>G8UKZ +M8^=7*6G9K8V!-B!XMFA8X*!&@RI&5NK7:2>F!H:(V!B6+S?WIT]OBGXF8I\' +MCU+N>U\WEU=IX>WMR<@8%F9X8&"XTFKFJ.:'Z3<K_OI>>.!X/K__OR>WIZ[& +M?N_'WTHNF]^GI\<I28'MK;>(:"968`"@Z,ZFEK9J=W?_Z^OO9J`@B'(+:C_7 +MJ6_F!LH?/XOB^[]O6W^I"<GA+5&WJ!;>:("`&"@F1I;F8T?GK^-O[U8@6*A^ +MWO+'B:G[)G)/?XLBVT]3^BMG*>DIH:VMZ7:&@J@`P!CH]BBH?F]'W^\_Y]\V +MH-BH-JBF1\D7NU)SIP.2JA\?:ZX[QY>WE]E1+8GF>A.H0,#X:(BX*)(/I^\? +M-\?_YOCXB&@(9L?IAQL3AY]";J_GDY)28V>W!_>9$2UY,O]GUD#`.$B8&"BR +MVS-SQZEGDXIV./C(:$;SQ^??9\?_ZDIOIP,24LM/?U]'"4$M@>_'*?Z``#AX +M(*!H3D**D[?I1Z^/:HC8..BH9CLGAP<'9S]3;Y_O6JY*PY.O)Y=Y<1$))\FW +M"``8N."`F#9>'BJGZ2D?OP?R^'@HZ`BV,Z>?)[<W)P]_IX/RHNMKNQ,GU^'1 +M`7=)><L8H`B@P&!(EM;F8W=IMW^W%Q[XZ/;(.(8/L_LG5Y<_SX=G6ZYJXZLB +MXP<IX9$A*5E)TCBX"(#`(#AH:.;OUZDGAZDWY@CVJ/A()LMRJD<I]S\'5\=+ +MFG/[KBZOY[_)\0&IF:%_*`BH(,!@6,C(J.*'U]_G*>FCJ(:F"/C6`MZ>GQ>W +M7S?I=V]+;UNN,JJS^Z=A,6D)@0GNUF9(`&`@F#BXQOO''X\7*9<BAL+V.`BF +MWM9"9V?GMRG71U^_/PL2(DMK>@=A`9=Y`1<^IE(X`""@&)CXMMH/^P^I%W<? +M.IHF*.C&!JA.OS^?1ZG7]\=?G[MR2KJ24KN7X:&7X>$G2@I.H.`8(-B@N+;N +M*PH'=V<71_-:_O:HMA96SOM3)Y=7UZFWI]]CPOJZCJX*,TGAJ?D!*:_3&P@@ +M>*!8V*!H9L)N4_=?-RG'BDJ2UA9&ED8RKS]'=Y>IE^<_;\M"HI)NKJXK:>$I +MR4$)O_]3J"`XH*#8(`@VSI[[MQ_'J5=#:HMF-D9&QOY+\R<'MU>7!Z?_<_IB +MDHY.;@)[Z2'I.<%I)Z=O*%BXH%B@H,C6)H:+)P]GU^F/F^\N9D9F!B8:`U_G +MQY>7QZ<?[YM*\M(.?GY2XM\9.5=A6;<G9UKX"#C8V""8R/;VAC/OGX<IJ4\/ +M3Z*&ADXFIH+3_W]G-W='AV<_>SH";E[FWLZNZG<9B0DAN?<?YXX(B$CXH-@X +M"*@6WKKO3Z=7%]]OS[N^ILZNCD(SWU_G1W='YU]/$\NZXI+NSA)ZRHK#IX?G +M_T_G7T-[*E*>3A[&MD;&=I;V1N9^4FKS[T_?_U/S;Y/[6V,CFSM+HY/S4X_/ +MCX^/@\L[J]HB@C+*CZ</_[>W'P_OJE)NIC:6EE8HJ-9VAOYRRF/OST_/[Q.O +M+_/#D^_O+R]O3T\/[^^O,R/+:@(2DN[.#JY2\CM?YW_'UT??G^^ZPM)>!D;V +MUJA65G:&?JX*(Z]O;^]OCR\O;P]O[^^OK^]O;X\/[Z]#N^IZ0BYN;HX.;BZN +MHI.G/Z>7UP<GIT.B@@Z&1D:6J-;6%L8>;B*[,X\_SR^/OV^O[Z_3KU/ST^\O +M+R\3@]O+"MK"4NYN;NY2<N+Z>HM_AQ_G%Y<GW_^;(H(.YH;&=A9V%I;&IKZ2 +MBGLS+^\O;[^_SP_/SX_O+V_O4Q,#8Z/+*KJZFL+R0K*NKG)R\F(:VBJ/YU^G +M=Q>')Z<OJKIR7F8&EE;65JAV9GY2.KOS;V^O;S\_3P_/SX_OK],O[R]S0X.; +M:XKZVMJ:HD(RPF("`H*B^CI*J@/_IQ^']\=?G^^K`BX>9@8V%A9V=C;FSL+* +M>Y,O+Z]O#X\/#V\O4_.#XP/SD]/3<\-C6\OJJJK*&B("PL(R<@*:>MJ:NDOO +M#^]?!V=_/^_+.L).'EZ&-K:V-D8F#N(J>Y./+],O+U,O+Y/S,R,;HZ-C$R^O +M+^^O0^-["^OJ6K+RDF[.;E*20J+Z2KHZ.T]_3^<WAW]/TXO*PDY^GN9&1K8V +MQB:^\HJ;0W-#`\.#`Q.O<S/S0P/#LU///[^_OP_3PWLKZDH"KBYN3KX.CBXR +MPJ(Z"@HJ"S/_'_\GAU^/K^,*(I+._A[FQD8&9J9.<LJ;8X-#\[.#8P-#LP,C +M8_.O+^]/GY\_#^^3H\L*&H(R+DY.;@X.TN+:RFN+Z\M["^KJ"V/#H[-O;W.# +MXYL+:MK"<NX^GIY^_CYN8CK**HO[&WN;([-S<_,S<],3<U/O;V\OD\-;B\KZ +M^CJ:XB(:XK*R,C*"8@*B>EI:.DI*JHL+XZ^O4P]/[U-38TOK2L)R$HZ^3KY. +M#NZNPJ):RJOKR_O;H\/SDU,O[V]OCX]O+Z]3LX/C&VN*FL)2[HX.CFYN+G(R +MPN+:BHN+"YM;^_L;FR/S<Y/O#^^3\X.;RXK:XK+NSDX^?C[.CJZR(CH*JLL; +MXT/3+V\/ST\_/P_O[].#&TN*^OI:@L(R4E(2+FZN,C(R(OIZ^KH*JPO+>^,# +M\Y-STR_OK^_OD\-#6RH:HO+N#DZ^3KX^SBY2\AH*ZCM;H[,3<W.OKU.OKQ,3 +MD\,C(UO[2XNJ*BKZ`H(B\NXNDM+20@*B2NKJRZ-;6X-CH^/C6QN;>[L+B\N[ +MBZOK:^I*"KH:VMI:&II:6AI:6DHJRBIKJJN[^SN;6QN;&WM+2WN;.\N[2VLK +M*RLKJRHJJBJ*:NKJZHK*"@K*RHJ*BHJJ:ZN**NOJRJHK:NJ+RVL+N\N[F[L+ +M2SL+:VLKJBIJRIKZ"FI*.BJJRFKJ^KHJ.AKJ:^KJ"XMK2TN+^QN["SO[2TL+ +MZ\N[BXM+RXL+JXHJJPHZ"FJZ&AIZ2LHZ"NN+Z^N+2[MKJ^LKZNJKJFKJJJL+ +M>_M[FWO[RVLK:CKZNKIZ&KHZ^OKZ^@IKBXN[^[N+*FKJ:BHK:VL+RXMKR[N[ +M^WL[2PLKJJNJ*NKJB@I*>CJ*BLKJ*VN+BVL+"XM+2PO+.VN*JBMJ"DI*:BKJ +M"NHKJJJJJJMKJFHJJFIJJJHKZVMK2TL+BXN+:ZLJ*^NJ*BOK*ZLKJHKJ*LI* +MBBIJ:JJK*ZOKBXO+NSL[^SO+ZZKJ:FJ*JJL*:JHJZJLJZBKJRFJK*FJKJBJK +MJNJKZZKK2TL+2POKBVOJZJIJBJHJBJJKZHHJ:NJK*^N+RPN+B^OKB^NK*ROK +M*ZHJJBIJ*JNKZFHJZHH*2FIJ*BKJJNMKBPN[NTL+RXLKZRLJJ^LK*BHJB@H* +M:JHJZBHK*ZOK*ZMKJXIJJRKJJXN+BXN+"VNK*XNKJBOKJBIJZBJJJBN+ZROK +MJVJ*:JHKZNJJJBHJ*^LKZ^NJJJLJ*JJKJZOK*ZNJZVLK*ZLKJNHJ*JLKZZNK +M*ZNKJZKJ*BKJZBJJJJLKJZNKJBJJJZHK"POK:PMK:VN+"XNK*JKJ2DIJ"FJK +MJZNKJNHJ*ZLKZ^LKJJJJZ^LK:VNKJJKJZNIJ:NHJ*JOK:^OKJRNJJJOKZRLK +MJROK*JHKJZHK*ZLK:VOKZVOK*ZHJJZLJJBIJ:JJ+:ZKK*VH*BFIJZJHKZVMK +MZ^OKZ^LK*^OK*ZKJ*BHJ*NKJJJNK*VMKZROKZRLJ*JHJZBJKZJOKJZJKJ^HJ +MJZNKJRNKJZJKJZNKJRLKZ^LK*ZKJZZNJ*ZNKJZKJZBHJZJJJJ^LKJRLKJJJK +MJZOK:VN+:VN+*ZJJJRIJ*NKJ*NHKZZNJJRLJ*RNJJJJJJJJJJBKJ*JHJJJNK +MJBOK*RMK*ZJJB^NJJRLK*ROK*ZJJJZNKJJJJJJJK:^LK:^LKJZNJZBKJ:@H* +M"HKJJBN+BPN+"PN+:^MK*ZNJ*JJKJROKZ^MK:^NKJBIJBNIJ:NIJZNKJ*JLJ +MZNLK*^OK:PN+BXMKJZNJJNKJ*JNKJZHJZBJJ*JJK*ZNKJRHJ*JLKJ^MK:^OK +MZVOKJZJKJNHJ*BHJJBHJZFIJ:HIJJBMK"XN+BXMK*RNKJPO+*RLKJRHJZBHJ +MJJNKJJJJ*NKJBFIJZBHJ*BJKJRMKBPL+:RNKJZNKZZLKJZJJJJNJ*^LKJRKJ +M:FIJJJNJJRNJ*JOKZVMKBVNK*RLK*ZNJB@HJ:FHJ*BJJJJNJJZLK*ZLKJJLK +MZXN+"\N+Z^LK*JJK*ZHJ*NKJ*NKJ*BOKZRLK*ZJJ*BHJJJJK*ZNKJRNKJJJJ +MJJJJJRKJZNKJ*BHK*RL+:ZOK*ZNKJZHK*^OKZVMKZ^LKJRKJZNIJBFIJ:FIJ +MZJJJJ^N+RPL+BXOKZRNKJZLK*ZNKJBJJJJLKJZNKJJJKJZJJ*BKJZJJK*^OK +M*^N+*XJZB@IJZVOKZ^LK*ROJ*NHK"PL+*RLJZPNKBBHKJHIZ"NKK*ZN+JVKK +M2VMK:PO+BXNJJZLKZ^NJ2DHZ2NKJ:LKJ*VO+2[M+BRNJJZH*RLHK\RM^&B-; +M8UYV6]?C&[O.IU?::.9_";?FJ([''R8H@I^_BZOOR[Z&<LN?YW]*AKI^GB(N +MTX?WE_?;!B9:ZPOB7OJ/6_XV!H+GQP_+"AO;0JZK\].;>WMJZ]LJ8HHZIL;Z +M,X._3R*K/^HNNV)B$T^:OD/S&]OZ0N)Z4J*S+[.JTA("ZR_OV]J[FTHB>FNC +MSUM":B+";L(K:L.#N[HJDY.#&OK+VCK:+G*+>QMC`VNZZRMJ^HJ:J_LZJOM+ +MJ@H+X^-[RRK*RCLJ\DJK*DHKP^-+JY*B^SMZ>DN;R^IB.H)J[W.ZHBIJ*NM[ +M8W/[.BI*^DN+ZEJB:FH"VOJJ,R/+BKK+BYM+NNO;H^J"R\LZ:KLK2JMK>XMK +MJAI*FIIKBHKKF^N:*TN[NZO*.@O[ZRMJR[N[^\JZ:TNK^MK:(CKKN\.CJGLC +M2YIZJXKKZRH*ZFMKB\J*:XL*NAM;JLKZ2FHJJ\O[*VNK>KJ+:OH[NRL["SKZ +MJCL[.ZHZJZLKNXOKBZNJ*^I*ZLOK:@KZBFH**OM;RZMK*J(*2PI*NYOK:[O+ +MZOHJRAHJ2XOJN\MJ*JOZFHN[ZHKJ*XN+:^J*"QM[NXHZJBLJBNJJ2WL[JQH* +MZNKKJHJJBSN+ZJL*:FHJRRN*ZFO+*XJKV_LK*ZNJ:FKZ>KH*:TLK*BO+*ZLK +MBFHJ.TN+N^N+"ZJZ"LKZ:BLJZFNK:FL+B\LK:HN[*DK*ZJH+RZMK"POK:^I* +MNFHJZJLJ*JH+ZRJK:BL+"ZHJZ^N+:TOKZ^NKJZOK:NHJZHOK:BHKN\MJVKHJ +MZPMJJFNJ:RMJJRJJJRLK*JMKJ^LKZZJKZXIJJJNJ:JKJJRLKZPL+JXL[:^IK +MZXI*JCMK:PNKJNHKZNJJZZJJJ\IJ*B)N4F+Z*LM[6R-C8V/CHUL;FSN["XLK +MJRKJ:HH*"LK*2LK*RLH*"HJ*:FKJZBJJJJNKJRLKZ^OKZ^OKZ^OK*^LK*RLK +M*RLK*RLKJRNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZO_ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +M____________________________________________________________ +9____________________________________ +` +end diff --git a/share/isdn/Makefile b/share/isdn/Makefile new file mode 100644 index 0000000..dbc7973 --- /dev/null +++ b/share/isdn/Makefile @@ -0,0 +1,20 @@ +# @(#)Makefile 8.1 (Berkeley) 6/8/93 +# $Id: Makefile,v 1.8 1998/01/03 14:13:46 wosch Exp $ + +FILES= 0.g711a 1.g711a 2.g711a 3.g711a 4.g711a 5.g711a 6.g711a 7.g711a \ + 8.g711a 9.g711a beep.g711a msg.g711a + +CLEANFILES+= ${FILES} + +all: ${FILES} + +${FILES}: + uudecode < ${.CURDIR}/${.TARGET}.uu + +depend lint tags: + +install: + ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${SHAREMODE} ${FILES} \ + ${DESTDIR}${BINDIR}/isdn + +.include <bsd.prog.mk> diff --git a/share/isdn/beep.g711a.uu b/share/isdn/beep.g711a.uu new file mode 100644 index 0000000..c1fc86d9 --- /dev/null +++ b/share/isdn/beep.g711a.uu @@ -0,0 +1,106 @@ +begin 644 beep.g711a +M/3FLS$"G:8A0,/F=I8UF'.2,Q^T11W:I+0V!,.1D;('=?3'6(,I9%_#<'."- +MY=VQ0#PL7ODCP'`#3:6]5TQD?):M;:&FBC&-<;A<A#S'G5TM:P#(Z4F8O-S0 +M\26E+;@\3!BY"<@PJ*U=?6$LY*0`<<UQ[P:9+5&Z/(3<:+VES8D`@(LY?NR< +M;+E=)<T[3'SPER&[X)B!?9T1`"3D+*%-[<DV'_&MZ>SD)+#M)7T!H)"(Z>>P +M/,RN_>7]^6S<;)*!28B@*4T=[=9<9+P?34T!ON:AT:%`I.1LP:5=K:BL`._I +M2(Q,&&WEW;%P7#SX80$[F$HM?0UG/(3<"(W]K1_H1[$!"'SDO'?=)0UOK%"6 +MZ<(0S+`QI:4MF-S<\'EQ2:CVP;U-6>QD)##1G0TYB":AP8L,)!RH/>4]F9!L +MX,<W(&S021TES2+\)&PGT<$K*,F-3;'`Y&2,(9T]03:X-X$I$*2DP&WEW3%@ +MS!!""080K!I-)3U)#.3\UA&MB7:OT4U1:%R$_(_]':V;H"89>:!\I"Q!):7M +MZ,R,R`F'X%#(+:6=P=#D7`!!;0$"IF&-+2^\A%PXS:4-B2"8-]EF#%S,*5WE +M3?^,O$#W.78P(`$=W:T@I.0LF0VME[:IK>VY+&3D<*VE_8%XP%XYWQ"</$8] +MY7U9+'PL(J'G((`IO5V-'AQDO).-C2&F.L$M80`D9(SAI=U1MG`8]^F@3/S@ +M;>5=<4`<3$BA&79@`NT=32E,9-PX[;V1TS:YT;'HG&3\/QVEC1]P,"Z)ANP\ +MD$$EI>T(?)RPN0'GF*@Q?3UAK&0D<''];0FHLT'QLPSD7+B])3T9L*PX5Y]` +MS"SI'25-;[RD[!\Q6;;(^<W]D6`D9(R9_;V!QI;Y,8G0)"3P+24=\:!LL$,I +MR.QLGDTE?1EL)+S6,3&GB'\M/2TVW(1\*KU]4?LXCX&A(!PD;($EI>TVC"S6 +M:8KP[)@M)=WQ\"3<@(&MV09^04UM!TR$I-B-W8UIF%8YX<;,)+QGW>5-Q^S, +MX'>IF*P`@=VE+?A<)"RY[?&/]CEMC=FL9.30$5T]@<B@SZ$?K%Q\:+WE?2$0 +M/-#K^6ZP,%<]I<WK?.1,:^WM.<;/D8W!@"1D#-G='='F`*A):6#\',`MY5T1 +M8/P,:'FIF+#.;5T]N0QDW/BM#4&Z7B'MD1:<A'S*?:6-YT#@?[FH#)RL`:4E +M;98\_``)H4Z`"'$=?<$0Y"1P0;TMUW:7$=&?S&2D6,TE/=F`<':)PQ#\C#<= +MY;W'S-PL_P$I.)@9/9U16"1D#$F]#2$&+F'1N=`D)-!1)1WQ>*P@9Q>@S,QV +M3>6=X2RD3)8!X0Z8IVU];<Z<A'QNS3V1ZRCI\>$@W.0,H:6E[:8LD)YIAJS, +MX*TE71'`7)Q@X?&IB!YQ/0TIS(2D(.V=;2G(@N$!!KSD_%N=)4T7K.R8UZ<` +M;/!A7:5MZ!RDK(E180[66<U-X5!DY*SQ';WAZ(AI@:<LI-QX3>5]83#,,%-I +MZ*S0-_TE3=\\Y$R:K1%WUL<MS?$@)(3,29V=$9Z@HJ$)P!Q<<*WE7=&@3.QV +M2:\`T(:-I?U9;.0<>)%M(7[208VM9IR$G!X]76V'8$CIF8A,7&PAI26-ILQ, +MX&D)"/!XD=T=\3`D))"!#9%?1KDM+;<,9*3@C:6]V2"`NODJ+!S,3YWEO:F, +M?-#_H6-@X-G]W2VXI&0,Z<UM>0;O\2T9$.3DK'&EG?'(<,@I=P`\/`C-Y1V! +MT!P,-N&Y:.!?#1T-6WR$?":-3;$BAEE1`:!<9$PY7:7M[A#`XVGHC#S`K26E +M4>`<_.!9@8/8YM&=33F,9*1@K?TM]RAG,;'F/&2<3GTE32F04"CINY!,T"&E +M)8W&?%Q0*?$YJ.CAO3W!D.3DK,%]S:%69J$Q!^PDI"`-Y7V!P&R`)Q?8;"Q? +M?26]%TPDS`)Q01N(5VT]T9BDA$PI_?WQODA'`3E`7"10$25=4?B,4-Z)WA#L +M5HTEG6$L))QX,5%)EKJ13>V2?(0<]DW=[6?89AFAR#PD#)FE)8TRC(R8Z<?@ +MK""1I=T1`"2D<.'MP0H&H8UMZ8R$)`#M74T9F)A'H1ILI#P:G>4]"2R\\-^Y +M1O#`&9VE;:C<Y(P7;:TIMC>M;>%PY&3LL:5],>@`YOEW,)Q\&`WE'<'P_&QF +MV8<@0+_-74UG/&1\QNT-84Z2`>VQ&%QDO"G=72W:L-BW"3A,G/`1):6MV'R\ +M6'F9-@"VK=T]H6QDI(#1O=&G-@E1D0X\9!SV/27-:;`P_@GN+/PLV:4E#2X\ +M')!7@0<82(']??&PY.0L83V-^78[P1&7[.2D`&TE?8'@K)B7!P!,C%O]Y3T) +M#*2,0D&AQGCI#7TM"*2$O+>]O4&^ECGQ&;"DY"PQ)5U1B.PPZNGH[`S(C24= +MP="D_/@!,6?(JZW]C?/\A-PH#9TM)T@3@6%(?.1,B5TEC3OL+&CI(S",@'&E +MI:T@7%SP65&AAL:!30TY;&0DL*W=S7E(J+F!>HPD?&;]Y3VY4`P`9ZGX+'!Y +M':6-)IPDC$<M<1_6:>W-`3#D9&R!W?VQUE@O(1>0W-S@C>4=L<"\K,ZYPK`0 +M@TVEO2E,Y/SVK>V9AMMQ#9&X7(0\QYW=+2M@*,FYV#Q<4/$EI2U(O,SX22F8 +M<"@M77UA+.2D@/$-,=OFH>VM"CR$7&B]I<UI8.`/^29L'(Q)727-&\S\,)=9 +M[@#8`9T=$8`DY"RA32UIML<1K6GL9"2P[27]@5CP5HE?\/Q,COWE_?GL'.PB +M82DX(&E-'>V6W&2\'\W-89Y.8:TA0"3D;,&E75%6T.!?*7@,O-B-Y=TQ\-R\ +MN.'AKEAJ[9T-![R$W`AM_='/J*GQP0B<9#SWW26-[U`0AFF^K$PP,:6E+7@< +M'+!Y,>F(]K$]3:'L9"0PT9V-26BNX;&K#.0<*#WE/7EP[*#WAV",4$D=)<TZ +M_*1LYQ&!KN@Y#;TQP.1DC"&=/<$VB.G!*="DI,!MY1TQ8`QPBHG6K"RBO27] +MN0PD/':1$:FH3ZU-K>A<A/R/_1VM2UCRH9D@G*0L026E[2@,;&@)3P"L2"VE +M'4'0)%R`0>UASIX!#>V/O(1<.,U=#6F@2"FA1@RDS*E=Y<U_C$P`=PEHD.`! +MW=VMH*0D+)F-T0>VB2UMN2QDY'"MI?V!^(`"F?_0'#PV/>5]6:S\K&K9$V`` +MZ3U=C3X<9+Q3C6U9YALQ[8'`)&2,X5W=T;8PN"GIX#Q\8&WE77'`G,P(6;EH +M`()MW4WI3&3<N"U-\1L&F:TQZ)QD_,^=I8V?\,"J"?9L_!!!)27MB'Q\P$EA +MTZ`H\7T]8:QD)/#Q/>WIUM\Q<3/,9%PX324]&4!0B"F/,+SLZ1TE3<^\7"Q? +ML?FHN)E-_9%@)&2,F?U-8<8&6?&)4"0D\"TE'3&@[`#/J7ALC*:]Y7W9;*2\ +MEK%!\TBG[?TM1MR$_.J]?1%KR(?!H2`<)&QAI:7MMFRLMFGN$&P8+27=\?"D +M'&"!T3F6/C&]C4=,A*38C1V-*?@&V6&V3"2\)]TE3<?LC*`7-Z`LP`%=I>TX +M7"2LN2U!._:9C0U9K&3DT!%=O6$(F`?A_RRDG(B]Y7TA$+R0HTF&</"I_:7- +M.WSD3#LMK8FVIU$-08`D9,P9W1T1YF`&^6D`?-Q`+>5=D6`\C*CY1R#POHVE +M/3D,9!PX48T!\DZ!;1$6G(1\.GVEC2?`6,<YZ,P<+($E)6UVO#Q@B9G&P,B1 +M'7U!$.0D<$%-K;<VZ5&MW\QDI%C-);T98+`FR4M0?`RW'>6]1PP<K!]A1]C8 +M63V=K=BD9(Q)30U9!LK!43G0Y.30424=,?A0V#=WX$Q,%DWEG>$L7,PV@:$& +M6.>-G6WNG(1\;LT]\3J629%A(%SD#%FEI>U>K/#R:9;L3."M)5T1P%Q\X"&Q +M1TB>$?W-Z<R$I"#M?>W7B*,!P<:\Y/P[G25-EU`LN*F/0`QP8:6E;2@<I%") +M$2%F5B%-36'09.2L,1U-(>BHN<&G["3<F$WE?>$P#$!/*4@L4#=])4TG/"3, +MBE%QYZAW[4UQ("2$S,F=?7$>V+/AR4#<I'"MY5W16,PLQLD*L*P&#:5]H6SD +MG/AQ+=GFXC$-K2:<A)S>/=UMYR#HR1G(O*1L(:4EC5[,S*!I*?@0F)%='7$P +M)*1P@8WQ+\:9[>TW#(2D8(VEO1F@X!.9VNS<3&\=Y;TI;/R0W]FRP&!9?=WM +M2*3DC.D-[4E&IY'MV1#DY*QQI9TQR#`HB?=`_#S(S>4=@="<C`8AZ3B`I\W= +M#<-\9'RFC<W!$A[AK<&@7&1,N5VE[>Z08$^)R`S\0*TEI5'@G#R@V>$R(.:M +MG;WYC&2DX*T]K0=6EW$Q)CQDG/Y])4VI\!#V:1K0O%`AI26-AOS<$"FQ:0AH +M83T]07#DY*S!?0T9UL[A\0?LY*3@#>5]80#L(`<W(`SL'WTEO5?,I`P:\8&R +MR"F-/5%XI(1,*?T],?Z(J4$YL*0D4)$E7=$XC!#N:;:L;*@-)9UA+"1\^+$1 +MZ:BKT;WM`GR$'/9-'2TG>.XA(;C\)`QYI26-PFQL..G?@"P@D:5=T0"DI/`A +M+8&N!N$-C6F,A"0`[5W-F7BXJ2$"C*0\`GWE/0DL3+`G"2@00-F=I6W6W.2, +MU^U1=_97+8WA<.1D[$%=?;$H8"X9]_`<G-@-Y1W!,/SLWID/@#"_3:5-!SQD +M_`8MC2$>.K%M,1BDA+PI'5TMHD`XJ<F8O!QP$26EK1C\3!CYN>A`]BW=_:'L +M9*1@$4V1S\8YK1&./&0<=CVES>G`P"))GNQ\[!FE)0T2O)SP5V%O(#@!?7WQ +ML.3D+&&];4GV#S'1%VSD)`!M)7V!X-!(J>=`O`P[?>4]"8Q<;-K!^:@8:<V= +M+8BD9$Q'O4W!_L;9D=FPI.0L,25=48@LP,,IR&S,2(WE'<'0I#RX@<%O.$LM +M_8TO_(0<*`U]K7^()T&!2'SD3(E=)8T[+*RHZ?J0#`!QI:6M(%S<,-D1>99& +MP;W-^6QD)$"M'0TY"$89`:(,))P&_>4]N=",8,>76.R0>1VE#=Z<)&RWK;%# +MJ,F-3<$PY&1L@1W]019X9V$7$%S<8(WE';'`3-#RR5YPT&.]);WI3.0\ME$M +M2;93$<T12%R$/`=]':V*X+;Y.:#\7%#Q):4MR$R,2,DWH!`H+:5]@:SD7&`Q +MC<%*IN%MK2H\A%R(3:4-Z>"@9YD&C-R,25TES:/,/$`7F89`6,$='=&`).0L +MH<VMJ;8742V)[&0D,"VE_8'8L`9)_Y!\O$[]Y?UY[)PL2B$WV.")O=UM]MQD +M3-\-#>&FP@&M(4`DY&P!I=W15A"@QRE83#Q8C>7=,?`<3,@AH68@JNT=S4>\ +MA-P(;3V14Y8)D4'(G&0\M]VEC>\0\#Z)YBR\\#$EI2WX')Q`^4$W.)8Q_;VA +M[&0D,!%];0DH:P$QJ\SD'.@])3UY\"QX%Z?`#*Q)W27-*CRD[&=Q(2:(><T] +M,<#D9&PA?;V!-JA)02E0I*1`[>4=L>",,%OIB"SL@KTE_3D,)+PV<7''Z-\M +MO:TH7(3\;SV=4:MX&^$9X)PD[$$EI2VH#.RHB9NP++@MI1U!$"3<8,$MH28^ +M0<WM3[R$7/@-78WIV.C)(3;,I$Q7W27-GVS,8!?I.-!@P=U=K:"D)*R9;7&? +MMDGM;?DL9.1PK:4]83@@X]G/K-S\=CWE?5FL_%!+F9K`0&D]I8T.G&1,KVWM +M>8;O<6T!P"1DC.%='=%&0&B)*6#\G&#MY5UQP'P,Z-EIN,""C5V]:<QD'$@M +MS;'J)J$M\>@<9/QOG:6-_S"`K\E6C'S0024E[6C\_`!)(2+@Z'&=_8&L9"3P +M\3TM5Y9'<1'SS&1<.$TE/9G`D*AIPY`\;.G=)4T_3-PL)\&)"#C9O7T1X"1D +MC)D]S2'&?N&1"5`D)'`M)1TQ6"Q@I]=8#`PFO>5]6>RD3+9!@=HX9VU][<8< +MA/SJ3?V1BFC7L:'@W.2,8:6E[4;LT"9I)E",6"TEW?$PI)S@89&)*,YQ/8TW +M3(2DV(T=;:FX3B%A]KPD/*<=)4W'+&P85V=@[$`!7:7MN-RDK$FM`<)V60W- +MH:QDY-"1W;WAB$A78;\LI)P(O>5](9!,\%,)UM"0J?VES>/\Y,R;+5&I=L>M +2#;%@)&0,F1V=D>;@SMEIP)S< +` +end diff --git a/share/isdn/msg.g711a.uu b/share/isdn/msg.g711a.uu new file mode 100644 index 0000000..d1cb02b --- /dev/null +++ b/share/isdn/msg.g711a.uu @@ -0,0 +1,1505 @@ +begin 666 msg.g711a +MRXL+"^OJJ^LJJBNKJBKJJJJJ*BJJJJHJZBHJJBOK"PO+2\L+ZRNKJJNKJZKJ +MBHJ*ZNKJZNKJ*JLK*ZNK*VO+2\L+:VOK*ZNKJRLK*ZKJ:HJ*:FH**HLKJRNK +MJJHJ*JNJJZHJJNMK:VMKZ^LK*ROKZZNK*RLKJRNKJZHJ*JKJZBHJZNIJZFHJ +MJJNK*RLKZVOKZ^MK"VNKJROK:XMKZ^NK*FKJZBIJ2FJJ:JKKZVN+"^LJZBJK +MJ^NKJJNK*^MK:^NKZ@I*RFJKZ^LKJZNJJROKZ^OK*RLK:^LKJZHKJRHJJZNJ +MZNJ*:BJKJRLKJZHJ*JHJ*XN+ZXM+ZROKJBHJZNIJBNJJJZLJZNHJJROK*RMK +MRVOKZRLKZVN+*ZHJZNJJZ^LK*ZJJJZNK*HIJ:FJ*ZJHKZZNJJJLKZ^OK*^MK +MBXL+"VOKZRLKZKIJJFJJJ^KJZBHJZBHJJ^OK:^LK*RLKJNHJ*BOKZVN+BVMK +MZVOKJRKJBHKJ*BHJ*JJKJJJJ*RLKJRHJ*JLK:XN+Z^LK*NKJZNHJ*JHK*ZMK +M2VOK:ZJK:VLKJBHJ*BHJ*JHJZBHJ*NHJ*BHJ:NJJ*^N+BXO+NTL+ZRNKJ^J* +M:NJJJJKJ:BJJJBJJ*ROKJZHJ*JKJZBHJJJHKZVN+BXN+BRLJ"PNK*RLJ*BKJ +MZJJKZRLKJZNJ*NHJJBLKZ^OKZRNK*NIJ"HIJ*JJJ*VOK*RNK*^LK*ROKBVOK +MZVMK:RNKJBKJZNJK*RNKJZOK:RNJZHH**JJ*ZJNKZ^LK*^MK:XN+:^OK*RLK +MJBKJ*JHJZNHJJJJJJBJJ*VL+BVOKZRNJZNHJ*JJKJBIJ:FKJJVL+"PL+"XMK +MZZNKJJHJZFIJZBKJ*JLJRBJKJNMKZVMK"\M+R\MKJRKJB@IJZNKJ*NHJ*BJJ +M*^LKJZLK:RNKJRLK:VLKJNKJJJMKR\MKJZJJ*NKJ*JHKZRLKJ^OKJFH*:BJK +MJRNKJHL+JJOKJZNK*JNJ*BJJ*VL+"VLK*RLKJZNJJJHJZNKJJNMKBVMKZZLJ +MZBJJJJJJJRNK*FIJ*JJJ*BJKJZNKJZNJJJJK*^LK*VL+RTO+BVN+*RIKZ^KJ +MB@H*:FKJZJHJZNKJJBMK"XMK:VMKZZNKJRLKJZJJJBOK*ZJJJZNKJZJKJNKJ +MZBJKJZKJZBJJJBKJJJLKZVN+BVOK:XMKBXN+ZRO+"RJJJNJ*BLK*"@IJZNHJ +MJRLK*RLK:XN+:^OKJRHJ*JNK*RNKJRLKJROKJZNK*^LKZ^LKJZLJZFJ*BFKJ +MJJNKJZNK*ROK:VMKZRNKJRLK:^I**NIJ*BHJ*JJKJZLK*RLK*^OKZRLK*RLK +MJZNKJZNKZ^OKJRHJJNKJZJJKJRKJ*JLKJZJKJRKJ*JLKZ^N+BVMK:^LK*VN+ +MZZLJZNKJZFJ*ZVMJ*BKJJJNJ*BJJJJNKJROKZVMKZVN+ZZHJ*BJJJJHK:XMK +M:RLKJJKJZFH*BFHJJBJJJJHKZ^MK:^LK*ZOK:VLK*ZLJZHJ*:BJKZ^OKZVOJ +M"BNJ*BOK:XN+:VOK*ZHJJJLKJZLKJZJKJZNKJZKJ:HJ*ZBJJ*^MK:^LK*RLK +M*RNKJZNJJZJJ*NHJ*JLK:VOKZZNKJROK*^OK*ZNK*NIJ*HMKZJNK*BHJJBLK +MZ^LKJJJKJROK*ZNJ*FIJBHH*"FJKZVMK:^OK*ZLK:PO+RPN+ZRNJJNKJ*BJJ +MJJJK*ZNK*ZNJ*FJ*:BJJ*JHKZ^OK*ZNK:HJKJBHKZ^MKZ^MKZRNK*^MKZ^LK +MJZLJ:HIJ*BHJ*JJJ*XL+BVOKJZJJ*FIJZNKJJJJKJROKZVOK*RLKZVMK:^OK +MZRNKJZNKJBIJBHIJ:NJ+R^N+B^LKJNIJ:NKJJJLK*ZNJ*BJJJJLKJROK:VOK +M:VLKJZOKZ^MKZ^OKJRHJJJNJ*NKJZNHJ*JJKJBHJZBJJ*VMK:^MKZ^OK*RNJ +M*JJJJFKJBXOK:VMKZRNKJZNJ*BHJJJNJJJHJJROK:RNKJZHJ*BJJJZJJZFKJ +MJJNK*^MK:^LK*ROKZVMKZRNKJBKJZNKJ*BMK:XMKZRNKJZHJ*FKJ:^MJJJJJ +MJRLKJRHJZNKJ*JJJJJLK*RLKZ^MKBXN+RTO+BVLKJBKJZBJJJBKJZNIJ"HIJ +M:NHJJBOK:XMKZ^LKJRJJ*NKJ*JJKZVMKBPN+:VLJJ@OKJRNJJJNKJZLKJRKJ +MBHIJZNHJ*BJJJJNKJZNK*RLKZ^OKZ^LKJZNJJJNKJ^LKJJJK*^OK*ZNKJJJJ +MJJNK*^MKZRNJ*FIJ:FKJZBHJJPMKJBLK*^OKZ^LKJZJKJZLKJZKJ:HIJ*JJK +MZRLK*ROKZ^OK*ZNK*RLKJZLKZVN+:VOKJRKJZFJ*:NHJZNHJJJHK*RLK:VN+ +MBXMKZRNJJJNJRHHKJZNKJBKJ*JJJJROK*RNKJZNKJZNK*VOKJZNK*BHJ*JJK +M*RNKJNIJZBHJ*BJJ*RLK*ROK:VMK:^LK*VOKZ^OK*ZJJJJHJ*BHJ*NIJBNIK +M*^JKJZLKZ^OK*ZNKJROKJZJK*VMKZRNK*BJJJJJJ*NJJJZJK*ZLK*RLK*RLK +M*ZNKJJJJJJJK*^OKZROK*RNKJZLKJZJJ*BHJJJHJZNHJ*HKJZZLKBVOKBXN+ +MBVMK:XN+*ZHJJJLJZFKJ:HIJZNKJ*BJK*RLKZRMKZ^MKBXMK*ZIJZNHJJJJJ +M*BHJ*JNKJZOKBPO+B^LKJZHJJJHJ*NJJ:RH*JBLK*RNKJBJJJJOKBVOK*ZJJ +M*NKJZJJKJZNK*VMKZRLKZ^NKJZNJ*BJK*ZLKJZJJ*JJJJJLKZ^MK*ZHJ*JHJ +M*BHJ*BOKZ^LK*RLK*ROJJHOK:XOKJZJJ*BHJZNKJ*BJKJJJK*RLK*ZHJZFKJ +MJJJKJZLK*ROKZ^OKZ^OKZVMKBXL+:ZOJZNKJ:FKJZNHJ*BHJ*BHJ*JLKZVN+ +MRXOK:\LKZJHJZBHJJJJK*ZNKJZJJJNKJJNMK:VOKJRKJZBJJJJHJJJJKJRMK +M:XOKJJJKZVMKZRIJ"HIJZJJKJZNK*NIJ*BJJJ^L+RSN[2TM+RPOKB@KJ"@J* +MBFIJ:NHJJJJJJJJJ*BHJJBOK"\O+"XOKJZNKJZNJJBHJ*JHK:XL+:RLKJZKJ +MZFH*2DH*BFHJ*BJJ*RLK:\O+R\O+"VLKJZJJJNO+JFHJZNJJ*BHJ*JJJJROK +MZRLKJROKZ^LKJBHJ*JLK*ZNKJZNJJRNK*JJK*^LKJZNJ*JJKJJLKZRLK*ZNJ +MJROKBXMK*RKJ:FHJJRKJJBHJJVKJ:VOKZRLKJ^MKJJLK*ZJKJBHJ*NHJJZLK +M*ZNK:VN+ZZLKZRLKJZKJ:NKJZNKJZBJJJBMK:\N+:VN+BXOK*BOK*ZNJZFHJ +MZFIJZNKJ*HHJ:RNJ:RLK:VMKZ^NKJROK*RNJJBKJ:BJKJZNK*BJKJBJJJZJK +M*ZOKBXMK:ZLJ*JNJJJLJZJJK*BJJ*JHK*ZNKJZLKJZLKZ^OKZZNKJNKJ*ROJ +MJ^LK:XOKZRNKJZLJZNJJJZLKJZKJ:NJJJZOK*RLKZ^OK:^NK*BHJJRJJJRNK +M*RNKJZLK*ZNJ*BHJJZNKJZNJJBNK*ZNJJBNKJZNK*RNK:\OK*XMKJ^H*"HKJ +M*JJKJNKJZNJJJJMK:^LK*RLK:PM+"XMKZZNJJNHJ*NKJZJJKJZNJJJKJZFKJ +MJJJJ*NHJJJOKZVMKBXMKZ^OK*RNJ*BNJBJHKJBMKZROK*^LKJZNJ*BHJ*NKJ +M*BHJ*JJKJJJKJ^LKJZJK*VOK*ZLKZ^OK*ZNK*BJKJJJK*RNK*FIJ*JJJJJOK +MZXMKZVMK:VOKZRNK*FL+JBJKZHJ*B@J**BHJ*JJK*ZNJJBLK:VMK"PN+ZRNK +M*RNKJRMK:^OK*^LKJNJ*:FH*"@J*:NHJ*BJKZVOK:XN+BVMKZ^MK"XOKJZNK +MJZJKZ@HJJVIJZNJJJ^MK:^NKJJLKZRLKJFH*"NHJJ^OK*^MKZROK*ZNJJJJJ +MJJJKJROKZVOKZRNK*RLK*RNJ*NJJJZNKJBHJJJJJ*NHJJZOKZZN+B^HJ*FKJ +MJJJKZ^OKZVN+BXN+:RNKJZNJ*BHJZNKJ:FIJ*BJJJRLKJRNK*VOK:^OKZ^LK +MJRHJJJNK*RNKJZHKZROKJ^KJZBHJ*BHJ*BJJ*ZNJ"TN+BVMKB^NJZFJ*:FIJ +M:BHJ*JJJ*ZLKZRLK:XMKZVMK"XOKJRHJJJNJ*BKJZNKJ*BHJJBLK*ROKZ^NK +MJBHJ*JOK:VMK:VMKBVNK*FIJ*VLJ*JHJJJNJJJJJJBMKZRNK*JHK*^LKJRNK +MJZOKZRNK*BKJ:FHJJROKZRLKJRLKJZNKJZNJJROK:VLKJBHJZJKKZRNKJZJJ +MJJNKJZHK*^NJ:BMK*VOK*RNJJBJJ*ZNJJBHJ*BJJJZJK*RLK*ZLK*^OK*ZLJ +MJJJJJJJK*RLKJZJK*ZNKJRNJ*BJJJZNKJZNJJJHJJJJKJ^NKJBNK*VMKBTM+ +MJJJJZNKJ:BJJ*BHJJJJJJBKJJJJK*^OK*ZLK*RLK*^LK*ROK*RLK*ZNKJJNK +MJZNKJBKJ*JJJJBHJJJLKZ^LKJZNJJZNK*RNKJJJKJZOKJRJ+B^MKZRLKJZHJ +MZBJJJZLJ*BJJJZJJJROK:^LKJZJJ*^MKZRLJ:FKJJROK:VMK:^NKJBHJJJNJ +M*BJJJJJKJRNK*^OKZ^LK*ZNJJZHJ*JJ+B^KJ*BJJJZNK*^LK*RNKJZJJJRNK +MJZNKJZNKJJNKJZJJJRNJJROK:VOKZXMK:RLJZNJ*:HJ*:NJJJZJJJJLK*^OK +MZ^OK:VN+:RLK*ROKZ^H*JJIJ*BJJ*BJJJRLKJJOK:^LKJZNJ*NHJZBHJ*NKJ +MJ^MK:^LK*NHJJBOK:VOKZ^OK*RLKJZJJ*FIJ:NHJJNMK:^NK*^OKZZLJ*BJJ +MJBKJ*ZN*JBNJJROKZ^MK:^OK*^N+:RNJZBJJJBHJ*BHJ*BJKJJJJJ^N+BVMK +MZZNJZHJ*:NKJZNHJJRLKJZNK:PO+NTL+BVOKJZLJ*BJJ*BKJZBK*2JJKJJNK +MJBKJJJJKJZLKZVMKZRLK*^LKJRHJJZJK*ROKZ^OKJZJKJZNJZFJ*:BJJ*ZNK +M*ZNKJZNK*JHK*ZNJ*BHJJRLKJRLKJROK*ZNJJFOKZBOKJZHJZNKJ*JLKJZLJ +MJJNKJ^MKBPL+BVLKJJJJJZNJ*JNK*FIJZNHJ*BJJJZNKJRLKJRLK*^MK:^MK +M:^LKJJJJ*BJJJBKJZNHJJBHJBHKKZ^L+BXN+:^LKJZKJ*JJJ*JLKJZOKZ^OK +M*ZLJ:FIJZJJKJZNKJZNJJZNK*RLK*^MK:RNKJZNJJJNKJZLJZFIJZJJKJZLK +MJZNJJJNJJJL+BZMKZZJJJRHJ*JJJ*JHJ*JJK*ZLKZ^OK*ROKZ^LKJROKZRLK +MJBJJJJJJ*JJK*^LK*RNJ:NHJJZNJ*NKJJZLKZ^MKZ^LKJ^KJ*JHKZ^OK*VIJ +M*ZNJ*RLKZZNK*VL+"PMKZRNK*FIJZFIJBHIJ:BJJ*RNKJBHJJROKBPN+:XMK +MZRNKJJNKJBKJZBJJJZLJZNHJ*BJJJROK:^OKBPL+"^LKZRJ*:FHJJZNJJBIJ +MBHJ*ZBHK*^LK*ROKZVMK:^OK:VOKZRNK*BJJJZNKJBKJ:FJ*BNJJ*^OKZVN+ +MBVLKJROK*ZJJJBHJJZOKZVLKJZLJJJN*BJLJ*JIJBNHJJRLKJROK:XN+RTO+ +M"XMKZZLJZHIJZNKJ*BHJ*JJKJZNKJJJKJZJKJ^IJZNJJ*VN+"PL+B^NKJJJJ +MJJNKJBHJJJLK*ZNJJXLK:JJJ*BKJ*JJJ*^OKZRNK*RLK*RNKJZKJ*JJJJJJK +MJRKJZJKKBPL+"VLKJZJJJBJJ*FKJ*JJKZRNJJBJJJBJJZ^MK:^LK*ZJKJJJJ +MJJNJ"NIKJZJKJJNK*RNKJZNKZVN+ZRNJ*NHJ*JNK*JJJJROK:VOK*RKJ:NIJ +MZJHJJJKJ*JMK"PMK*ZNJJJJJJ^N+ZZNKJROK*ZLJ:FHJJJLKJRL+*RKK*ROK +M*ZLKJRKJ*BJJ*RLKJNKJZBHJJJHJ*JHK*ROK:XN+:VOKJZNK*BKJJJNKJZLK +MJRLK*^LKJJJKZVOKJNKJ:HJ*:BJJJJHJZNJJZZL+^TO+RPN+BVLKJJHJ:FHJ +MZFJ*"@J*:NJJ*^OK*ZLK:^MK:RNK*ZNJJBHJJJLK*RNKJZNJ*NKJ*JOKZRLK +M*RNKJNKJ*NIJ:NHK:XL+:ROKR^LJ*ZJK*RNKJZJKJRNKJZJJJZNK*^OK*RLK +MJZNKJZLK*^OK*RNKJJNK*ROKJZJK*FH*"FKJZNHJJ^MK:VN+BXMK:^MK"\L+ +MZZMJ"HIJ*BK*BJIJ:JJKZVMK*ZLK*ZLKZ^LK*ZNJJJJJJJNK*NJK*RLK*RNJ +MJJJJJJJJJ^OKJFH*ZBJK*^NKJVM+2XNJ:@IJJRNKJZNK*RLJ:FHJJRNK*XNJ +M*FN+ZZIJ:JJ+RXLKJZJJJJHJJJOK:XLKZ@J*ZBLKJVK*"FJJ*RLK*^MK"VOK +M*ROKZRNK*BJJ*ZNJ*NKJJNN+"XOK*^OKJRIJ*NL+B^LJN@HJZJJJZNJJ*^MK +M*ZJJ*JNKJ^OKZVMK:RLJZBHKBPOKJZLK*RNJZNKJZBJJ*FHJ*^MK*ZJJJBN+ +M"XLKJNKJ:HJ*:BHK:VLK*NHJJ^OKJ^M+BVL+ZZJJJJJKZZNJ*NKJ*NIJ:FHJ +MJRLK*ZLKZVMK:^NKJZLKJRKJZBJJJZKJZJHKZXN+BXMK:PN+ZRNK*RNK:@I* +M2HJJJRKJBHHJJZLKJVHK"PN+:ROK"PN+:RNKZVN+ZZIJ"LJ*BFIJZJOKZRLK +M*RMKR\OK*HIJ*JHKZRNKZVOKJHK*RHHJJ^OKZ^MK:VOKJZOK:XOKJNKJ*BJJ +MZ@HJRPL+RRNJZNJJJBHJ*BOK:RLJBHKJJBLKJBJJ*RNK*NHJZ\N[.\MKZRLK +MZRNK*BHJJBIJ"@KJJRNKZFHJZXL+:ZLJ*JHKJNHJJ^N+BRNJJJKJ:XOJ"@KJ +MZVNKJZLK:PN+*ZHJZJJJJJNJJ^OKJRHJJBOKBXLK*NHJJ^NKJJJJJ^LKJNKJ +M*JJJZFKJ*BMK:ZMJBNJK:VN+:^N+"PN+*ZKJ*\OKJZJ*BFHJ*NIJBNJJJBIJ +M:JIKBXN+*ZNK*VMKZZNJJJNKJBIJ*BOK:ZNJJBMKBVLKJZLK*RIJBHIJ*XO+ +M"^NK*JHJZHH*:JMK:ZLJ*JNK:JOK*JKK:VOK*ROKBPL+:RNJ*JJJ*FIJ:NJJ +M*ZKJ*JJK*ZNKJJHKBXMKJZJJJJJKJRKJ*JJKJBKJJNL+2\N+ZROK:^NJ:FKJ +MJRLJ:HH*BNO+JZHK*XL+:ZOJ:NJKZRLJ:NJKZRNJ*JJKZXN+:VOKZ^NKZFKJ +MJBOK*ZHJZBJK*ZLJZJKK:RLJBHKJ*VN+*ZLK:PMKJRJJZXO+:ZNJ*JN+JXKJ +MZ@KJJRLKJRJKZVOK*RHJJJJJ*HH*BBHJ*ZNK*VN+:^LKJZHKB\MKJNKJ*BKJ +MB@KJ*XL+BRNK*VN+:RNK*JHK*ZMJBFKJJZNJ*FIJZBKKBZKKBXN+:ZKJ*BOK +M*ZLJZBKKBVOK*ZOKZ^NKJBJK:PMKJ^KJZJJJJFH*BNHJ*NIJ:BKK"\MK*RLK +M:XN+:^LKZ^LK:LH*:JOKZRLKZPO+BRI*ZJKJ*RNJZFJ*:NIJ:FJJZ\N[RVLK +M*RLK*ZLJ*JOKZRLK*ZNJJJHJZFHJJJHJ:FJJ*XO+BRLJJBOK*RHJZNJJJZNK +MJRMKRPOKJZHK:^NJJBI*BBKJZFJ*ZJN+:^LKZVL+NTO+BVOKZRNKZFKJ*BKJ +M:HIJ*JNKJJHJ*JNKJZHJ*JKKBXMK*RLK*RNK*BJKBTM+RVNKJJHJ:HK*RHHJ +M*ZL*NNKKZXMKZVN+RPN+*RHJ*NHJ*NIJ*JJKJRHJ*JHK*ZNK*^MK"XOKJ^N+ +M"XOKJNIJZJJJ*NIJZBMK:RNJJBOKBVNK*BJJJZIJBFHJJJJJ*NL+ZXN+ZRNJ +MJRN+:ZNK*RLKJZNJZBHKZRNJ:FHJ*^LKJBHJJ^OKJNIJZJMKZZKJZBHK:RNK +MJRMKBVNJZHKJZ^MK*ZHJJRLKJZKJZJHKZRLK:HKKZRIJ:JIK._M+ZZNKJZNJ +MZNJ**JJJJBKJZJLK*ZHJ*JLK*ZOJBNHKB\L+ZZJJJJLJZNHJZTL[2XOKZVN+ +M:ZLJ:FJJ*NH*2DH*:BJJZFIK"RMK:^N+"TN[BZLJ*BHJZFJ*ZNL+2XOK*BHJ +MJZNKJZJK:VNK:@H*"HIJZNHJ*BMK:^LKZXO+2TN+JZLKJZLJ*BKJJRNKZHIJ +MZNJKJROK:^NKZRH*:FJJ*RNKJZOK:VOK*ZJK*^LKJZHJJBOK*ZKJZJKK*ZKJ +M*BJKZRLK*ZNK*RNKJZHJ*JLK*RHJJBMKZZLJJNL+2\OK*ROK:VNK*@H**VOJ +MZFJ*ZJJJJBHJJBMKBRNJ*JHKZ^NK*BJK*ZNKJBJJJXN+:VNKJZNK*NKJJFL+ +MRXLK*BJJ*JJJ*BJJJZLJZNIJ*JJJZNHJJ^MKB^OKBTL+BTLK:NJJ*NIJ:HHJ +M*ZLJZFHJJ^OK*RJJZXL+B^LK*VN+B^LJBFJJJRIJ"@HJ*^LKJJJKZVOK*ZJJ +MJVMK*RIJZBN+RPMK*RMK:^LJ:HJ**@MK:FKJ:BHJZFKJ*PM+"^LJZBHKZRNJ +M*BJJJ^J*R@IJ*XL+B^N+2SL[RRNK:PO+"RLJ:FKJ*FK*2LIJJBNJ:NHJJZOJ +M:FKJZPL+:ZLKZVMKZFHKJRL+B^LKJZNK:PN+Z^OKZ^LJBLH*ZJOK*ZHJZBJJ +MJBHJ*JHK*ZJJ*JJKZVMK*ZJJJJLJ:FJJ:\N[2XOK*^L+:ZLJ*JKKZRK*NDJ* +M:JJ+*^KKB^OKZZNJ*^N+B^NKJJNKJNJ*:NJK:XLKJBJJZVOK*ZNKZ^NK*HIJ +MJNOK*^LKJRLK*FJ*ZJOK"\L+BXL+"XNJBLH*:JHJ:@K*BJHK*^KJ:XL+RVNJ +M*BJJJROK*ROKZVMKJRHJ*VN+ZRNJJRNKJNKJZBJK*ZLJZNKJZNKJ:NJJ:PN+ +MZRLK:XN+ZZIJZBJKJZLJ*JKK:RNJ*BJJJZJKBRLJ:^NK*FKJJNOKJBKJ*NN+ +M:^LKJZNK*FJ*BNJKZ^NKZBJJZVMKZZNKZVL+:^NKJROKZZIJ:FHJ*BJJ*JMK +M"POKJNKJJRLK*ZNJ*^LKJNJZNBHJJBLJJVL+2PLKJJHK:XMKJ^IJ*JNKJZJK +MJ^MKZZIJBNHJJROJBBHKZZLJZBJKB\M+:^MK"POKJRKJ*BOKJFJ*BNJK*ZNJ +M*JMKBVLJ*FLKJXMK*ZJJ*^OKJ^IJ:JHK*ZHJJJNKJ^J*"FJJZ^LKJJNK*RNK +MJZJK:XN+ZZNKZVOK*RKJ*JJKJRJ*BNJK"\N+ZRLK*RLJZHKJJBOKJZKJ2HHK +MJJLKJ^N+"XLKJZLKZ^LKJBHJ*JJJ*NHJJ^N+:RNKJ^MK*ZHJJJJKJZIJBHHJ +MJRNKJZJK*^OKJZNK*VN+ZZHJJBOK:RLJZBJK*ZNJ:FKK*RJKJBJJJRLJZFIJ +M*BOK:^LKZXL+B^NKJNN+BXOKJFJ*BHJ*:NKJ*BOKJZJJJ^OKZ^OK*XL+:^NJ +M*JIK:^LJBLJ*ZJHJ*JHKBPO+:ROK*VJJ:VJ*ZBKK:VMKZ^OK*RNK*NHJJBNK +MZHKJJJNK*FKJ*BOK:^LKZ^MKBXOKZ^MK:^NK*FJ**JNJ*NJJJROKJ^IJ*NMK +M:ZLJ:FKJZNKJZBIK^\OKZZNK:PL+:^MK:VOKJRKJZJOKZZOJ:NHJJJJJJJHK +M:^LJ:FKJJJNKJBHJJ^OKJ^IJZJMK:VOK:XL+RXLKJBJK:^NJZBHJJ^MKZZNK +MZVLJJJN*:JOK:VLK*NIJ:HH*"NJJZ^LKJZJK*^MK*ZJJJVO+BZMJ:JN+"VOK +MJ^L+BVNKJBMKBXOKJNIJZNIJRKI*RFHJJBKJZJKK:VOKZROK"TNK*NMKR\N+ +MZRLKZ^OK*ZHJJJLKJ^IJBNJJ*FK*RFJJ*^NKJJLK:VLKJJLKBXMKJNJ*:NHJ +M*^LK*^MK:RNJJNN+RTMKJZJK*^NK*BJJJVLKRDJ*RBJKJZJJJJOKZZJ*R@KJ +MJVOKJZOKBTO+:RNKZVN+:^LKJZNK*FJ*:NJK:^NJ*JJK*ZNKJZLK:VNK*HH* +MBBJJJJJJJ^MKZRLKZ^OK:PM+*ZOK*ZLJ:FKJ*BOKJRKJJFOKJZJK*VN+*RIJ +M:NKJ*BJJ*BJKZ^NK:HIJJVN+BXN+BXN+*ZJJJJOK*ZLJ*BJJ*ZLJZBHKZRLK +M*FIJZJHK*XKJ*ZLK*ZHJ*BJKZ^NKJROK:VNKZBJJZXMKJNKJJBOK*RNKJRLK +MJRKJZBHKZRLJZBJKJZMJBNJJZPL+B^OK:VLK*NIJ*JLKJNIJ*JJKJRKK"ROK +MB^NJZFHJJROK*ZLK:PL+*^IJ*JOK*RIJBHIJZBHJ*JKKBVNKJBHJJBMKBVOK +MB\O+BZNK*XN+:ZLJJJJJJHI*2DJ*JJNKJJJJZXMK:ZN**XOKZZLK:XL+RXLK +MJRMKZZOJBFKJJJNKJZJJJJKJB@IJ*NN+ZZNK*^MK:^LKJ^L+"VNJ:@H*BFIJ +M*NKJ*JJJZNJJ*XM+NPMKBPM+NPLK:PNKJZL*2KI*"DI*BBJJ*VMKJRHJ*BOK +M:^OKB\M+RVNK*JHK:VOKJZJK*RLJ:HIJ*JNKZHH*"FKJJJJJ*XO+RPN+ZVN+ +M:^LKJBJJ*^LKJZLJBNMKZHJ*:BJKJRKJ:BHK:VLKJROK:VLKJBHJ*^OKJZNK +MZ^MK*ZHJJJJKJZKJZBHK*ZNJJZLKZRLJ:NJJZXOKJNHJJ^LK*ZJKJ^OK*ZOJ +MBJN+JJHK*JJKZVNKJJJJZPO+:RNKJZKJ:FIJ*NN+:RNJ*JJK*ZNJ*JJJJZHJ +MZNJJZVOKJZJJ*XL+BZNJJ^N+:^OKJZNKJZKJ:HIJZBKJ:NJJ*FHKZZJKB[M[ +MN\MK*RLKJRKJ:NHJ*BKJ:FKJJJNK*BJJ*VMK*RHJJFN+:^NK*BHJ*JJKJBN+ +MRPMK*ZLK*^LK*FIJZJHJ:@H*BBJKJZNK*RO+R^KJJJN+RXNKZBJK*^NKJBHJ +M*^OKZROK:XL+RXLKZBKJZ@I*2@IJJ^NKZNHJJBOK:VMK"PN+*RKJZJHKJZJJ +MJROK*RKJ*BMKRTO+ZRLK*^I*BFH**BLKJ^IJBNJJJJJK*VM+2XLKJJMKBXMK +MJZJKJRNJJNKJ*BLKJZJJJJLKJRHJZJHK:^LJBFKJJROKJZJKZVN+:^LKZVMK +M:^NJJBJJ:RL*:BHJJBIJBHIJ*JNKJJJJZPL+BRNKZXL+ZZNJ*JOK*ZLJ*JHK +MZRLJZJKKBVLKZHJ*:JJKJZHJ*JLKJRKJ*JOKB^NKJRMK:RNKJJLKZVNJBJNK +MJNOK*ZNKZXN+J^IJBFHJJBIJ:NJJJJHJ*BJK:XL+"PL+"TO+ZZOJZNIJ:@I* +MR@KJ*JNKJJKK:PN+*ZLK:PL+BRNK*VOKJFH*"NJK*XMK:BHKJZHJZBHKZ^NK +M*FJ*ZJLK*RNK*^OK*ZNK*VO+R^NKJJLKZZLJZBHKBVLKJNIJ*BHJ*JJKZVMK +MJ^IJZJOKB^NJJJJKJNJ*"HJJ:PN+*FIKBVMKZ^OK:PO+BROJ:NJJ*ZOJBNJJ +MJZIJBHJJ*^LKZHIJ:BJJ*JJKZPO+BRNK*XO+BVMKZVL+BRLJBHHJJRNKZFIJ +M*JJJZFKJ*JKK*ZN+"ROKJVIJ:NJK*VOK*RLKZ^LKJROKB\L+:^NKJJJJJNJ* +MBNKJZFJ*"FJKBPN+ZZLKZ^NKZNKJJBOKZZLK*RLKJBIJBBHKZRLKZ^L+R\L+ +MB^IJ*ZIJBHHJJVN+BZNJJRNKJNJ*:JKK:ZOJ*JJJJZNJJZJKJRLKJZJK:PL+ +M"VOKZVN+:ZOJ"@J*BFKJ*JJKZRNK*^OK:PN+*ZIJ"FHJZ@JZJBNK:^NKJJMK +M:^MKZROK:XMK*ZLK:XN+JRKJ*JHJ*NJ*BBHKZ^LKJZOK:RNJZFJJZ^NJZHKJ +MJJLK*ZKJJBOKZRLJ*BOKBXLKJZOKBXMK:XNJJHLK:NKJ*BOK:ZOJ:NHJ*FH* +M"HKJJJIJ:NJK:PMK:XO+N_N[:ZNK*^OKJ^KJ:BJJJBIJZNHJ*BHJZFHJZVOK +MJZJK*VN+ZZJK*^NJ:HH*ZLM+:VLKJJOK:^NKJJHK:VNJ:HIJJ^OKJ^KJJBOK +M*ZKJ*BL+"POKJZJJJZHJ:@H**JHJ:NJJ*VMKZRNK*XL+B^LKJRLKJZJJJJLK +M*ZOJBFHJ*BKK*BHKZVMK*ZNJ*VN+:ZOJZBJJ:LI*2HJKBVLKJROKBXMK:ROK +M:XL+B^NKJZNKJRKJZNKJZFIJZBHK*RLJ:HIJZJJJJZJK:XN+:RNJ*NL[R^OK +MZVN+:ZMJ"FHJJZLJB@J*JJNKJBJJZXN+:^OKZVMKZ^NKJBJJJFJ*BFJJZVOK +MJZLK*RNJZFKJJNMKZZJJJJJJJNHJJBL+2PLKJROKBZKJ*RJJZ^NK*NIJZBHJ +M*BJJJRMK:RNK*^MK"\OKJZLKZRNJ*NIJZBKJ:FIJ*JLK*RLK*VL+RXOKJROK +MZ^NK:NJJJJKJBHKJJBLKJNHJJJKKR^OJJBMKBRNJZNJKZ^LKJZOKBPN+ZZKJ +M*JLKJ^J*ZNHJ:HH*BNJKZ^NKJBMK"PL+BVL+RPLK*NJ*:BJJJNKJJ^OKJFJ* +MZBHKBVNKJBOKZ^LJ*BNJJRNKJZNJJRLK*ZLKZRNJJBJKZ^LKJBJJJJJJJBJJ +MJJJJJJJKJJNK*^LKJZNKJZJJZFKJ*BLKZVOK:PO+"XMK*ZHJ*JHJ*NKJ*BIJ +MZBOJBJJJJJNK*RNK*^OK*^OK:XN+ZRKJ*JJJJBMK:VMKZ^LKJJJJ*NKJ:NHJ +MZFKJJZNJJBOKZ^NJJRLK:^NJJBLKJZOK:VOKJZLK:^LKJZJJ:FHKJBJKZVMK +M*ZHJJZHJJBKJ*JJJ*JJKJRHJJJOK:VOK*ZLK*XN+ZZLKZ^LKZRNK*ZNKJRJJ +M*FJ*:JLKJRJ*"FJKBPOK*RNKZXOKJ^J*:JM+:RJJ*JHK*ZLJBFHKB\L+JBJJ +M*\L[RRMJ"NHK:VNKZNJJZ^NKJBHKZRNKJNJ*"FJJ*ZIJ"NHK:^NK*BJJJRNK +M*^LK*^OK:VOKZXO+2VMKZVHJ:ROK:VN+*ZLK*HJ*:FIJB@K*"HIJB@K*"HHJ +M*XM+2\M+N[O+R\L+:RNKJ^LKJZNJJZNJZNJJJJKJ:FKJ*JJJJJJJJZHJZFIJ +MZNKJ*JN+.VNK:XMKZ^NKJ^LKJZJKJROKZ^LKJZNKJ^OK:VOKZXL+BXLK*^NK +M*FIJBHJ*"HIJZNKJBHKJ*JHKJZNKJZLK:VN+:RNKJJJK*PM+RPL+2\NK*VLJ +M*VMK:^NKJNKJZNIJZBJJJBKJB@H*"LJ*ZBJJJBJJJRMKZ^OK:XMKBVN+BXN+ +MRTN[RXOKJZLK*ZHJZBHJ*BIJBFJ*"@J*"@K*"@J*JXNJJVMKBXLK*ZHKZXN+ +M*ZHJ*JLK:XMK:VO+R\O+RPMKZ^NK*NHJZNKJ:FH*RLH*"LI*RLH*:BJK*RLK +MZXO+RPN+BXMKZVN+RPN+:VN+"POKBNJJ:FIJZJJKZ^NKJZHJ*NIJZJJJZFKJ +M*BLK*ZLJ*JHJ*NKJZNJJJJHK:PO+2PL+"\M+2TL+:^LK*NIJZBKJZNJJJZLK +M*RNJZFJ*BFKJZJOK:HKJ:HIJ:NJJJROK:^N+"\M+2\O+BVMK:ROKZ^LK*ZNJ +MJBHJJNKJ*BHJ*NKJ*JHJ*NIJZFH*"FHJJZN+"PN+Z^OK*ZNKJ^N+"XMKZ^OK +MJVJKZZJK*RLKJRIJ:NHJJJKJ:BHJ*BKJ*BJKZVOKZ^MK:VOKJJJK*NIJBFKJ +MJJNJJROK:XL+"PL+"POK*ZLJ*BJJ*^OKJZKJZBKJ*BJK*RN+"RIJ*BJJZNHJ +MZFJ*"FKJ*JLK*^MKBXN+BPL+R\O+"VLKJRKJZBHJZNIJ:NHJJZNJJBOKBVOK +MJZJJJBHJ*BHJJRLKJBJKJZJKJBHJZNHJ*ZIJJ^LKBXN+"\M+N\L+BVOK*ZKJ +M"DK*"FHJJZNJZNHJJJNJJROKZZNJ*BJJJJJJJJJK*VOK:^NKJZNKZ^OK*^LK +MZ^OKZVLKJZNJ*BKJ*BIJJBN*BJJJ*NHJJJLK:PL+:^LK*ZLKJBKJZFIJ:NKJ +M*BMKZXO+RPN+:VMKZRLK*RLKJBHJ*JHK*RNK*ZHJ:FKJZFKJZNHJJBHJJJHJ +MJBNK*VNK:NO+:PL+"PMKZRNK*VMKBPLKJBIJ"HIJZHKJJBHJ*ZNJZZLJ*ROJ +MJ^NKZ^NKJJKJ*JJJJROK:ROK:XMKJ^IJBNJJ*BJK*^LK*ZHK:XL+ZPN[ZZNK +MJVKJ*BKJ*BKJ:FIJ:BJJJJHJ*NHJJBOK:VMK:VOK:XN+:^OKZVLKJFIJZNHJ +M*JJK*^LKJJLJ*JOK*^N+:ZNKZLK*"@J*:NJK:VN+ZRKKZZHK*RJJ*JJKJZNK +M*VMKBPN+"PN+BXMKZ^LKJNIJBHIJ:HH*BNKJ*BKJZBJK*^OK*ZNKJZNKJJLK +MJROKJZLJ*BN+"PL+R[N[RPMKJNJKZVHJJNIJB@I*2HKJZNJJJBHJ*JHK:^OK +M:PN+"XOKZRNKJRNKZ^OK*RLKZRLK*RNKJZJJJRHJ*BKJ:NIJZJLKZRLKZVMK +MZ^LKJBHJ:FJ*Z@I**JLKBPL+RPN+Z^LKJJJKJZNKJZLKZRLK*RLKJRLK*^NK +MJBIJBNJJ*BHJZNJJJBHJ*JJKJJHJ*JHKZVN+BXL+B^OKZ^MKZ^OK*ZNJZNKJ +M*^MJ*JHJ*NIJZNJKJJJJJNIJZBJK*ROK:VOK*RLKZRLKJZLKZ^OKZ^OK*ZNJ +M*NHJ*BJJ*ROKBXN+:VOKJZNKJBHJZFIJ"@K*R@J*:BJJ*VNKJ@L+:PL+"PL+ +MBVNKJZNKJZLJZNKJ:BJJJJLK*^MKB^OK:^NKJBIJBFIJ:NKJ:NKJZBHJJROK +M:XL+"\N+:VOKZRNK*ZNK*NKJ*JOK*RNJJFMKZJNK:NKJ:FJ*:FKJ*BHJ*BOK +M*^LK*VN+BXN+BVMKZ^OKJZJJJJNJJNIJBFKJJJNK*RMK:VMKJRHJJZLKZRNK +MJJJJ*NKJZNJJJBKJJBMKJRJ+:^MKZZJJ*BJJJRLK*ROKZ^OK:^MK:^LKJBKJ +M*JJJJBKJ:NIJBFKJ*JHKZVN+"\N+:^LKJRLK*ZNJ*NIJ:BHJJRNKJRIJZNHJ +MJJNKJRO+R^N+BVMKZZNKJRNKJZHJ*BHJ*JHK*ZNKJJHJ*BJJ*BHJJBOKBPL+ +MBVN+:^LKJZNJ*BHJZBJJ*JJJ*NIJBFKJJBOK:VMKZRLK*ZLKZ^OK:RJ**FJ* +MZNJJZPO+BVOKZRLK*RNJ*NKJ:FIJ*BHJ*RLK*RNKJRLKJZNKZVMKZ^LK*ZJJ +MJBHJ*BKJ:FKJJBOK:VLKJZNK*NIJ:BJK*ROKZZNK"XNJZ^OKBVOKZZNK*RNK +MJBIJB@K*BFKJJJHJ*BJJJRLKJROKBPO+"PO+"XMK:XN+ZRNJ*BHJ:@J*:NIJ +MBFKJ*BLKJBKJ:NKJ*BN+R\L+BVNJ*@N+ZVMK*^LKJRHJ*JHJZNKJZNHJ*JJK +MZ^OK*^LKZ^LKJZJKJZJJJBHJJROKZRNKJZNK*FH*"HKJJBOK"PN+:VN+"TM+ +MRPN+ZZKJB@I*2NJ*2FHJZNKJJJLKZ^OK:VLK*RLK*^OKZVMKBXOKJ^IJ:NKJ +MZBJKJRHJJZJJJJLK*RLKJRLK*ROKZ^OK*RNK*BHJ*BJJJBJJJBHJ*BHJ*JJK +MZNHK*BJJJ^MK"PN+:VOK*RLKJZLKZRNJ*NKJ*JJJJROKZ^OKJZHJZNIJBHJ* +MZJHKZ^OK*^OKZ^MKZVMKZ^OKZVOKJZLK*RLKZRNKJBHJ:NIK*RHKJFJ*"HIJ +MZBHJ*BHJJBJK:VN+"PL+"XMK:XN+BXOKJRKJ*JHJZNKJZBKJ*BJJJJJJJJJJ +MJBJJJJHJJJLK:^LK*ROK*ZNKJRMKBXL+BZJJ:ZOJ*NKJJJJJJJNJJJLKZ^OK +M*ZNKJRJ*R@J**JNKJZNKJRNKJZNK*^MK:VOKZRNKJZJKJRKJJJJJJZNJJROK +MZRNKZRNJZNIJBFKJ*FJJB^NJZ^OK:VN+BVOKJZJK*^OK*ZLJZFJ*:FIJ*JNK +MJZNKJJNKZVMK:VOKZ^OKJZJKJRHJ*JJKJZLJ:FKJJBMKZRLK*RNJJBJJJRLK +MJZNK*ROJ*NNJJJLK:PL+"XOKJZJJJRHJZHH*"HIJJ^OK*ROK:^OK*RNKJZLJ +MJJJK*^OK*RLK*ZNJJBHJZBHJ*JKKZVN+B^LKJRIJ:BHJJJLK*RNJJHNKZJNK +MJZNJJRLK*^MKZZNJJJJJJZNK*JNJ*JNKJZJKJZJK*^OK*ZLJZBHJ*BJKJZNK +M*^NKJRLK*^OKZZLK*ROK:^MK:^OKZRNKJBHJJJNJR@JJZFJ*"@J*BNJJ*^N+ +MR\N+BXL+"PL+BXOKJBHJ*JNKZ^LKJ^IJBHH*"HJ*:FKJ*JKKZ^OKZ^OKJZJK +MJRMK"PL+BXMK*ZLJJBHJ:HIJ:JJ+JRHKJZJJ*VOKZRNKJJHJZBJJ*RNKJJNJ +M*BJJJZNKZ^OK:^LK*RLKJZJJJ^MKBXOK*ZLJ*NHJJJJKJBIJ"@J*:BJKJRMK +M:VN+:VN+Z^MK:^JJB^MK:^OK*ZNKJZHJJBKJ:HJ*B@H*BFHJJZLK*^N+"VN+ +MBPL+"PL+:RNJZFKJJBHJJBKJ"LH*BNHJJROKBPMK*ZNKJJLJ*JLK:VOK:ROK +MBRIJJBKJ*FIJ:NJJ*RLK:^LK*^OKZVOKJNKJ*JHK:XOK*RLKJJJJJJLKZ^MK +MZRLK*ZNK*NJ*BHH*"@J*ZJOK"PN+BVMK:XOKJJLKZ^OK:RN*ZJOJZJJJJROK +MZZLJ*JJK*ZNJ*NHJ*JJK*VMKZRNKJZOKZVOKJBHJZBHJZFIJZBJJ*VN+"PL+ +M"PMK*ZJJ*^LKJZJJJBKJZHJ*B@K*"FKJ:[N+:\L+BVOK*ZKJ:FKJJJNKJJNK +M*JHKZXL+RPL+RVNKZFKJJBNKJBHJZ@H*"@J*:BHJJJJJJ^N+"PL+BVMKBXMK +M:VOKJZNJ:HIJZBHJJBNJBBHK*JJKJJLK*RLKJRNKJRLKZVLKJZNK*ROK*ZNK +M*ZLJZFKJ*JJKJZLKJZNJJJNKJZLKZ^OK*RN+BXMKZRLKJJJK*^OK*ZIJBHIJ +MZBKJBNJK:NJKJJJK*VN+"\O+RPMK*ZNKJJNKJNIJBHK*6JI[._LJBZNK*RKK +MJRNJ*JJKZ^NJJNKJZBJKJZNKJZNKJ^OKJZHJ:NJJJZHK:XL+"XMK*^IKRVN+ +M*ZNJ*BKJZNHJ*BKJZFIJ:HJ*BHJJ*^OKBVMK:XN+ZRLK*^OKZZLJJBKJZBJK +M*ROK*ZNJJBHJ*JHJ*BLK*ROK:^LK*^OKJZHJZFKJ*^HJJZJKJNHJJRLKZ^LK +MJBJJJ^L+R\L+:VOK:VLKJZNJZBHJZNHJZHJ*BFHJ*BJJJJJJJBOKBVMKBVLK +M*ZLJZJJK*^LK*RLK:RNJJBLKJRK**BLJZVOK:^OKZRNJJFJ*:HIJ:NHJJRNK +MZVOK*RLKJRNKJZNKJJJKZRMK:VLKJZHK*ZHJ*NKJ*NHJJ^OKZRNKJZNKZ^LK +MJRJ*"HIJ*JLJ*XNK*VLK*ROKZRLKZ^OKZROKZZNJJBKJJROK*RLK*RLKJBHJ +M*FKJZJJJJZHJJJJJJJJK*ROK:VMKBXOKZVOK*RNJJJNKJRKJZBKJZBJJJBLJ +M:JNK*JLKZVMKBVMKZZLKJZHJ*BKJ:FHJJ^LKJZJJJBMK:^MKBVMK*ZJJ*FJ* +MBFKJ*JJKZVN+BXN+ZZNK*NIJ:NJJ*^LKJNJJ*^MK:^NK*FN+JBN+ZZLJJJKJ +M:NKJZBJJ*JHKZ^OKZ^OK*ZNJJNHJ*CIZZVO*XAK;^]M;<Y,#0SO;*^KBLF+B +M6G(:RBHKRJNKRRHK"ZJ[.QM+RTN["^NK:DHJ*HHZ*BO+JLLKZ\NJ*JIKJRLK +M*NIK:JMJ*^KKBJIJJ^JK:TNJ:[N*JBLK>BK+B[J*BZIJ*\NKJDLK:BM[*XK+ +M^\I*BRHK*ZOJ2NLKJJJ+RVJKBXLK*BNKZJKJRNKJ*@J**JHJRJOJZNHKJVN+ +M"SO[2TO[^XN+2^OKBNMJ*FJKBHJ*BFK*:@HK"FJ*Z^M*:^L+*BMKZPLJ"RMK +M:VMK*@M*ZFN+:^L+JVOK*TK**ZH*>FJ+*RKJ^\NJ"FH+*VL**[N+*[IKZZK* +M*POJROH+"JI:NSLJ*FH;JTO*JVMK2OHK*TNJBSO["ZJ+RRLBCHHCJYH[;\,+ +MBZ,C*]IZJZHBPOHKJ_JZ:_N+:BI+.VHZ*HNJ^@H+"RMJ:\N[ZPKKRVMJBJK+ +M*XJKRTMKZ^NK*NH**BOJ"JLKZFHKBXLKBXLK*ROJZJHJZNOK:NJJ:^J**XOK +MJBLKJZMJJ@N+*ZIK"VLJ*XNK:FJK*RN*"BNJBLH*JBNJJRN+:RHK"PNJ*NOK +MZBIKBVOK*VOKJJOJBHIJ*NHJ*JOKZBNJZJJJ*ZLK"PMK*VN+:ZLJJJHJZJOK +MJBOKZZHKBRNK*ZLJZFHJJNHJJBHK*RNJ:BKJ:JJK*^MKZPOKZ^LJ*NIJJZLK +MZRLK:VN+ZZL+*^HKJJJJ:FJJZFIJZJLK*RLK:POKJJLKJRKJJBKJ*FHJZZJJ +MJBJJ*JKKZVMKZVN+B^OKZRNKJBNJ*FHJ*ZJKJZNJ*NKJ*NIJB@HJJFHJJXL[ +M2^N+:RLKJZNJJJOK:^NKJJLKJZNKJZHJ*BLKZRNJJZJJ*JJJ*BJJJRNKJZNJ +M*ZJJ*NHJ*JHKZ^LK*RLKZ^LK*^LK*FIJZJJK*^OKZZLKZ^H**BJJJJKK:XOK +MJZOKZZIJZNKJBNJJ*ZLK*^LKJZOKBVOKZVMKJZJKJBIJ:NHJJJNK*ZNJ*NJK +MJZJJ*^OK*^OKZRNKJJLJZ@J**BJJJZOK2\LK*ZLJJJJJJNKJ*JNK*^MKBVMK +MZRNJ*JJKJZHJJJHJZNHJJJLK*RLK*RKJJROKZRLK*RLK*ZNJJZNK*^LKJZHJ +MJJHJZBJJJJHJZNKJJBOJZNNKJ^LK*ROKBXMK:^OK*^MK:VOK*RLK*RIJ:FIJ +MZNHJJJHJZFKJ*JHK:VOKZ^OK*ROK:^NK*NKJZNKJJBOK*ROKZ^OK:POKZZNJ +MJRHJ*@O+*VLKZNJ*"HKJJRMK:VMK*RNJ*BHJJJLKJZHJJJNKJBHJJJJK*ZNK +M*^MK"PN+:^LK*ZJJJJNK*RLKJRJ*"@KJJJLKJZJJJJJJ*ROK:VMK*FHKJBHK +MZ^OKZ^LKJZNKJZLJ:HKJ*JJJJJNKJZNKJRNKJ^N+"XMKB^OK*RNJ*NJ*BFIJ +MBHIJZBJJJRMK:XMK:VMKBVOK*ZHJ*BJJJJJJ*JJ+ZRHK*ZJJ*JJKJZNKJJHJ +M*BHJZBJJJJLKZVOK:XN+:XN+:RNKJNJ*"@J*BNHJ*BJJ*JJJJ^OKBXOKB\O+ +M2VOKZROKZ@H*RFJ*BHJ*JJLK*VHJ:ZLKBXN+BVOK*RNK*NHJJJLK*ZKJ:NHJ +M*JJJJRLKZVN+:^OKJZLJZNHJJRLKZ^OKZ^OKZRNJJJKJB@H*"HIJZBHJJJJK +M*XL+"\O+"XL+.\NKZRLKJRIJ:FHJ*BKJZBJK*ZNKJRLKZ^NKJJJJ*BJJJBJJ +M*ROKZ^OK*^OKJZHJJJJKJZJK*^LKJRKJJJJKJJLKJZJKJZNKJZJJJBMK:^MJ +M:BNK*RNJJZLJ*BJKJZLK*ZNJJZHJJ^MK"PN+B^LKJZJKJZJJZFIJZNKJ*JJJ +MJJOKZRNK*ZNKJJJJJBNJZBHKZRLKZRMK:^LKJJJKJZHJZTLKZJJJJJNKJRNK +MJZNJ*BJJJRLK*ZJJ*BKJ*JOK*ZNJJJHKZRLK*^OK*^MK:^NK*BNJZBJ*JRJJ +M*LKJ:JJJJFOK:^LKZRLK*ROKZ^OKZ^LK:BHKJBLKJRNK*NHJZFKJZNHJ*BHJ +M*BJKJROKZ^L+"PL+"XN+:VLK*ZNKJRJJJBHJ:FIJ:NJ*BNHJ*BJJJROK*RLK +MZ^MK:VLK*RLKJZNJJJL+*ZKK*ZHJJBNKZNKJ*FIJ*BIKB^NKZJNJJROK"RLK +MJJNJJJNJ*BHJJJLKZVN+:RLKJZJJ*BHJJROKZRNKJJLKJBHJJBLK*ZJJ*RLK +M*RMKZVHJ:RLKJRHJ*JHJ:@J*JFN+ZRHJJ^LK*RNKZ^LJ:HJKBVLK*RNK*BKJ +MJ^LKJRKKRVLKJRMKJ^IJZBLKJRLK*^J*ZBJKJBHJ*\N+JHK*:NO+2ZJJRPNK +MZJIK:RKJZ[N[:XI*:BNJZ@KJ:ZL*RNIK:ZMJ:HL[NRMJZJKKZZLK*^OK*ZHJ +MJJJK*^LKJNL+R\LK*FKJ*HI*^CJ*Z\L+JBIK.\M*.NJ*JNKJB[L;N^J*BBIK +M^_NKZNHJZLJK:XO[*^JKJZK*:BLJRGKZ"CNC"[JZ:UL#VVI*ZBHJ*KHZ*[N[ +M:PIJBNJKBDJ*RSN+ZXK*:SL;H_N*FKIJ*DN;:PIZ.DK*B_M+>YMK^J(*2P-[ +MND(""JL[.PM[RZNK*JOZ&CKJ6UOK@N*+(P,+FMHZBTMKBVJK^_M;F_MKFOHK +M.RO"4F+[`]N*\IH+*^N[6_OJVIIJRX/CBVK*BIKB*SLC6\J"PLHS0WMKJBKJ +M:FIJJKO+J^M+REI:"GM[ZNHJ"HH*JRJK2PM[VXNZHGH*RV/[2KH**GN[B[M[ +MRV)BNFH;N[L+*POB&FHJH^H*^KI[2LL[ZW.#^PIB>MK+`YL[JPJZ.FO+R^OZ +M.FHK&JZ2B@/#^RHJN_N[:FJKZFMJJ]O[BTJJB_M+PD++LV-*VN+*K^]K,O)Z +MJVL*(JIS[WMBLB(J(^I:@FLO(^NB&N/;PZLNKIHC&WLC._OJ,L+JVWL[:ZJZ +M(AHJ(R.;(^JBLMI[F[-*@@J+TQN+2MH["GHZVJM[VZM"VBN;PVIB0JMOKQMJ +MR@MJ:ZJBRSOK*OIJFNH[2DI*JNKJB^M[`QL:\J+;+Z^;X@)JJNNZHCJ[\P.J +MFF):RAMS@SOZKFZ22R_O0[I"V@NC,]LKVBXR6DJKBP.+*YL#$]OZ[FXZH\,C +MBYHZ"X.;"B+R^@LKBHK[^RN[8UMJ:RHB&LI+ZTLCBCK[6VMB,J+Z6]MK2EJ+ +M.R.["HLKBZNKZQKZ*RNKZ]OC>R.JFLJ+>\IZVEIKF^-*TF[N6@OS&WIRPN./ +M?^_+NB++XY,O>WH.TLNOOV/Z$@)J:FJR;M)JHR/3,TJ"`LHZNLI2TH+*REI* +MJM-/[YM"DJ*;4R\ODS.34S.+*NH+@R_O(WN*HC)J;X^#SC:6!J[BHLYFAF9. +M0DMCNRLZJAMS;Z\OCZ>'7Z_*VK-G]V>GESDA65=F&*`XMA)B9BAH*$:F;A*N +M+BXNWC;6MH(':6D'JOY.`P>71W_O0S,[6_<AK8W1]V"LK.`ZJ;=&^&"87N^W +MZH;(:&Z*6^;VWJ=Y^2D2:(@VT\=7QY/;(Z='QU^K(KN)D>W1%UCP<$@;-XK( +MV&!HVU<IR@;XR$8>$C8&WJ\IJ4<B7H[[MY=W'P/_E[EYR3<K^D/_IUO2-I:F +MPL-*?JC(Z`;+ZZ9H2!;"IY_J'K[;IS<'IP^_Y[>7-^?3R_O/QY<79\-R_GYF +M-E:HE@9>IH;&QB;.0@+N?J8..R?W-X<_'_?Y`7'QH5MX`&!(\C^OCE8HEBY_ +MU_?N2.#@^';Z6\/CPV.C4P/S$]-O'Q=YL2WM07_8,$`X;J.N%H@H;M_'!P=_ +MYEBP\`!H_TDY5WLVJ)Z_UY<?*M,YD6WM@1+@P!@>+YHHF'AV/^D7KP(NSI:8 +M`$!8SFG92?/HN/:?:>DG.R?9$>T1B0@`8"A/]RMH&$C.]XD'CI869B8H6&`8 +M3NG922-H.!;OR9FY5ZF9`;$ACTC@>.;/_^[H2/8CE]=3!HC("&AH:"CF(P>W +MGSJF_GOWN1E9H2$A.:<&R$AV6O.J7A867NOO$^KF:/B8N.@&;KKC[S]O8ZN+ +MYPDA`<'AR1-&Z*@>"Y/*WD8&CNK[^M+>]HCX&/@HWHL3\X-;`],?=PEYH>$A +M^;>NJ&BVPG.O>J;&7A):PF[>9O9HN#@(-G)S[P-*HC+C=_DAX>&A23=KAJB6 +M7F)KVCZFOO*R;AXF!L;6"#C(EA)/)__C^L**YXD9(2$A>>GO9NCHQ@*#6U(F +MIHYR[MZ&QL;6"#C(EM(O?S_OPVOKW^F9H2$AF6D_WJ@HQO)+JPXFWJX"CN;& +M!L:6"'AXZ#Y3IY^/\S-SIRGY6:&AH3DW(M9H5C[K.S*F7E*"CH9V]@9&Z#AX +M"`:JCX^/CW^_3^<I^:'AX:&)#^;HZ+9NHF(.#O+2GD9VQGY.-LB8.*AN([,# +M[Q_G/Q-/U_DA@6$AB2\&B`BHIG*:XEJJPJ9V5C8>;@9H>/@HOAL3#W\G9\_; +MPT=)H6%A89E'_HCXR/;.`L*"RVN^-JC6YC*^UDBXZ"9*NR//AS=?"T*3ESDA +M88&!68?VF%A(M@Y2KNJO<[ZHB"@F@J[VB`BH7EJK.Q_WUX<JGD(GZ3FA@;&Q +M><*8X%AH1F;>RJ<G"Q;(*.::J]Z(2*CF+B*J[S?7YZI.+L,WJ=>IV3$1`7\( +M6#AH:+AH$D=W6T;H]NXNYL:V5E86=I[31S='I]/;*X(Z;\>I:0DA<?')_@@X +M.#@8>,8?-^]27AX.OL:FHCXHN&A>K^=/3P='ST)FWCM?)R='*:%1+6&::+AX +MH&!@:.?I7Y).6GI.9H[ZIJC(B,::VX]'5P?K9K82&_/S_S?IB;DQ[?&G5LB8 +MX`#`>,\)-\O*XTNF*)8:HR;(2);.0CJ?J2D?/K8.>VK2JX?I:1<I08T1OU:6 +M:.`P,)A?"3^"CP<[ELA6H\]>R$B6YH9.'PF))QJFYH;F[L]7Z:DIZ0G!;7'# +MACX(0'#`^&/W6P.7MR;(*`;"&@Y2#JC(5B+/1S?'AR]F*(9+SS_G%XF)-U]I +M\>U9QDY[2/#P6'8J;H:?B?_H:([R)I;>/W\.]O[#N[*Z!ZF?GB9**MZF8]?I +M1Y]'-Z\[F2TQNFX7JV#P8#B6MB@RUS?F=F/[!I8.;Y-Z\B_WCZ8^___.9C*O +M8\X>FX>G<T^'YS,J:YMJ/AHA[;&:AUFZ,/"8V*#X5@\IQ^[SZ7OH5H*N5I;N +M7\?S$ZFY1YXN[SH6%K([XB(/][</X__GRQZN2TI2^N.;QT&M26+)Z7B0($B` +MX`B>CX>?,ZEW)I:2ZY;H?DLS6W]7:6G7-R>;+F;V=F9".X_?)R?_,^I*&JY2 +MXEJB^JH+>P.[6F*K"3$Y_NF99@!(GN!@:#XFII/3![>*:G^?)@9S2_["W^?O +MGR=GIR\_'Z,.S@HR?FY+T^,C6QO*+L*+BZ)J(\N*BOJR6HOK2NL[@LYS*0GI +M1RD7,D8V-KCX5I86-E++"V_/I^>_0QOS&@[J,R/[O^<_CX^/<^,[HEIB3G[N +M`BZ2*LOJ&LJK>QOKBR,CZ[L+\AH#"Z)#?R.KHZLNKK_)^4='.7<VZ!YHX-@H +M*`@&R@M3S_]GA[_;;^_"$J,ONX.G)___)R</RZMCXN9>8JZF<J,J<KI[>O+Z +M^R.+2S.3JP(J^PJB&X^S2WL;RG)N_FY/B>G?5PF_)G[."/CHJ&@HII(KKZ^? +M!X<??]\#*X,32RN3TQN;PX,JNNM;:QIJ:K(.+G+N+B**:@L#XX,#,_,#`[LK +MBPL+*DN;FVLKVPM:4A(N?AZN[]>W_REITX[+XHB(=E9H5MZ^6EMO9\<'YT=G +M0SL#.]+RJFHZZ@/S@UOCDZ,K2CK:4H[N4LY.H@K:.J,S(P,3$V-;8T-;:YL; +MJTIK>VOKR[LJXL+"[AX^>C.GQ^<WE[]JJFI&%@8VJ%8F7H;ZSV.']Z^WCQ^; +M#^^"/YJ:LBZRBZX;ST,#,Z-K>\O""RY^+DZ^KJOK0^\#0V-C8SO;`WL*J^K: +MFNHJRQNK"QMK.OI*6D(2DJXN2B^G?W_'YU.[8_HFIJ:&MF8^/E(Z6U-OSS_? +MSR^O`SNKBJ)"8L*B^NK+VP,#,S.CNPN*`O*R,I(""DO;@U,OD[,#FVIZFAHB +M`GJZ2BIKZRLK*^LJ"@HJ:IK*JLI:&OIZ:CMS#^_/?T_#"TNBC@YNSGXN`H*B +M"KO[&YO[&\LJZDO+JLO;6YMCPSL+2^NZ.DK:&LI*2BM+B[LCHWM;6PLJ*BO* +MNFJ*:BLK2@H+JWJZRPN**OL;*DJ*BB+R,H*:^@IK.YL[FZ/C8^/S,P,CH]NJ +M.KHZHD):>IHZ:BJZ.KIZ6J):HAJZ2FKK^YM[FSL;F]M#`R,C8^-;6]M[BZKJ +MNAIZNKKZNLI*^KK*NDIJ*FH*ZJOJ"@H*"FHJJBIK2PO+^_M+BVLKJBJKJRMK +M:XL+RXLKJ^KJZBJJJJJKJBHK:^HJ*RIJZNKJ*JJK*ZNKZRLJZNKJ*JJK*RLK +MZXMK*ZKJZNHK"PN+"TN[RXOK*RNJ*JOKZRNKJRNKJNKJZFIJBLJZ^DJ*BHKJ +MJJOKBXN+R\LK:\L+B^LK:^LKZXL+:VOK*RJ*RLJ**JHJJBNKJBJJ*BJJJZJJ +MJZHJ*VOK*VN+RPMKJ@KZFIIZ.@HJ*XO+2[O[^WO[2PMKJRJJ*RLK*ZLJ:POJ +MBNIJZNIJBHJ*ZHK*"HIJJBLKZVN+:VN+BXMKZRLK*VOKJNJKZZNK*^LKJZNJ +M*JJKJZJK*RNK*BIJZJJJJZNK*VN+:^OKJXK*"@J*ZJKJBNN+B\N+BPMKZRNJ +M*BJJJZHJ*NKJ*JHKB\L+ZRLKJZKJRDH*ZJHJZBJKZXMKZ^OKZPL+:ZJ*:FKJ +M*BHJJZLK*ZLK*RLK*RLJZNHJJZJJJFN[:RNKJJHJJNOKJBJJ*JIKBRLKZ^LK +MJFI*NKK*BBJKJZL+"PL+B^LK:\O+BVOKJRHJZFJ*B@J*ZJJKJJJKJZNKJFIJ +M*JOKR\N+*VN+:PM+*KKJJFJKZVLKJJNJ*JJJ*JOKZRNJJBHJJVOK:XOK*JJK +M*RNJ*FKJJBHJ*NJJ*^MKBXN+:RNJZBHJJBIJ:BJJJ\L+BNKKJRJJJRJJ*JN+ +MBVN+Z^JKBXMK*FHJJRLK*HIJ:BJK*RNJJZJJ"_N[RXNKJROKJRKJ:FKJ*BHJ +MZHH*ZBJJ*ZNJ*XN+"PN+*ZJJZVOKJVK*:NO+"ZOJ:JLKZ^LKZRKJ:ZMJZJJK +MJRJJZZLJJFIJ*NH*"JHKZPM+:^L+2PL+ZRNK*VLK*NJJZJJJBFJJZFJK*BHK +MZRKJJNO+"ROJZBN+BVOKJ^HJ*BHJBHIJ*NJJR\NJJVMK"XMKZZNK:^LKJBHJ +M*JLKZZNKJZLJJJJJZHIJ*BHJ*RNKJRLK:^OK*^IJZJJKZVLK*XN+RSN["^NJ +M:HK*2LIJZJOK*ZNJJFL+BVMJNNHJ:BJJJNL+"VMKJRHJ*JHJJJNKZBJJJJJJ +MZNHK"\N[RRLK:PO+RVNK*BJJ:HH*B@IJ*BOKJVH*:NJKZRNJ*JMK"PMKJJHK +M:^OKJZKJJ@N+*BNJ*JJK*VMK*ZNKZHH*BBKJZFKJJNN+B^MKBXN+RPNKZFKJ +M*JJJ*JKKZVMK*ZJ*2LKJJBKJ*JJJJBMK:VMK:^L+2TL+:VOKZVN+*^IJ"@JK +M*NKJ"HIJJBNJZNJK:XL+:RNK*ZJKJNHJ*NKJJBMKB^NKJRN+"XOK*ZJJZJHK +MJZKK*ZJKJJNJ*NHJJBIJBJJK:\N+:VOK*FHJ*^NJJJL+:PJ*:HIJZHKJJROK +MZRLKB[N[RXMK:XL+BRLKJZHJZJKJ:FKJJJHJ*BJJJJHJZNIJ:NKJJBNJZNKJ +M*VL+BVN+RPN+BVMKZZLKBXOK*ZHJ*ZJJZVH*:NHKBZIJ:HKJJZIJ:@J**BMK +MB^OKZ^MK*ZNJ*JNKJJLK*RLK*RLKJRLKZ^NJJFL+"POKJNKJZPMKJNJJ*XOK +M:DI*"NJJ*RK*NDKJR\NK*NKJJNMKZRLKZ\N[2[M+:RLK*VOKZFJK:XNK*JJJ +MZNHJ*JNK:DH*JFN+*^IJJBNKJNK*:JJKJNKJ*JLKJRMKB^MK"XN+:ZLKZVN+ +M2\NJRJHK*XLK*BJJJJJKJZNJ:NHJ*BIJ"FKJ*BJJ*JMKB^NKJZLJJZHJJRNJ +MJZNKBVOKB\M+RVOK"TO+"VLKJJLKJ^J*"FIJBFIJBFH*.OHZ:@MK*JMKB\MK +M*^LK*VMKZVOKJJHK:XL+2VNJJJOKZZOJBJKK"VNKJZLK*ZJJZHH*BFIJBHKJ +M*BKJ:BKJZJHK*ZNJ*VL+B^MKR[N["RLJJNMKJJOKJJJJZVMK"VOK:TO+:^I* +M2HKJZFK*^KI*"FK*RHKJ*JOKZ^OK:XMKBPO+R\O+RPM+BZNKZVN+Z^MKZRLK +MJJHJZNIJB@K*:JJJ:DI*2HHKJVJKJXH**JMKZZJKB\L+ZZNKZRL+NPNKJBMK +MR[M+2PL+2SN[ZVJZNLJ*BLI*2LJ*:NJJJBKJ*PN+:RN*2LJ*JFNKJZJJ*RLK +M:PM+BXO+R^OK"VN+2PL+"VLKJBJKJJJJ*JJJ*FKJ:HI*.KK*BFIJ:NJJZFKJ +MJBNK*JHK"TO+"XN+BVL+"VNKZPM+.TL+Z^O["[M+:ZI*2KJ*"DKZFII*JHI* +MBDJ*ZFHJ*JMK:PO+R\N+:VN+:^NK*VN+B^OK:VL+"PN+:VOKZRNJ*NHJJ^H* +MRLIJJRNKJHJ*:JJJZFKJ*NIJ:HIJJJNKJJJJJJOK"PNJJTO+NYM[^_M[^[O+ +M:VN+"^LJ"LI*2DKZ&MJ:.DK*RDHZNFJKBVLK:\N[.TM+2PN+:XMK:VOKZXO+ +M:ZNKJZNJJ^LKJNHJZVOKJFH*"LH**FNJZBNJ:HH*BNKJZJJJ*NHJ*JMK:^LK +MZPO+2PMK*ZLK:XN+:^OK*VL+BRNK*^OK*RKJ:FIJ:@H*"HJ*"@J*R@IJ:FJ* +M:BHJ*BN+"PO+N_O["TL["\M+"XOK*^LKJZJKJVH*"NHJJJNKJZJJ*RLJB@K* +M:JJKJ^H*2LIJ:HIJ:FJJ:XN+ZVN+R[M[^\OKZVN+BXLKJBJK*RLJ*JOKJZNK +MZJJ+JFJ*RLH*RDK*R@IJ*JHJZNJK*XL+BVOK:XL+"\L+:XL+"PMKJ^IJ*BN+ +MB^NKJJJK*RNJJJLJJJNKZHI*^OJZ:BIJ"FJJZ\L+*ZJJZPM+"^HJZRN+RVLK +MJBHK"\M+"^LKZVMKB^NK*JJKJRIJ:NIJ:LJZ2DH*ZJJKJZNK*ZNKJROKZVMK +M*ZHK*^OKZVMKBTM+"VLKJBJJJ^MKZ^OKJRJKB^I*RDJ*:HJ*BFKJZNHJJBIJ +M:NJK:XO+"PM+RPMK*^LK*VN+"XMK*ZLK:RNK*FK*"NKJZBHJJROKZRLKJRKJ +M:FKJZNKJ:@J*:BJKZ^OK:^LJ*XNK*^N+RTO+BXL+N[O+ZZOJZBJJZFKJ:FIJ +M:NKJZNIJ:FJJJZNK*RLKZRLKZVOK*RNKJJHJ*JJJJZJKJZLKJZNK*ROKZVMK +M:RLK*RNJ:TMK*^OKJ@J*RHJ*:NJ*"@IJ:BHK*RNK*XL+"^LKJZLK*^OK:^LK +MZ^MK"XN+:VOK*BHJJBKJ*NJKJZLJZHJ*BFJ*"LIJZJLKZVMKB\L+"POK:JL+ +MZXN+*ZIJBLIJ*NKJ*BJK*HO+*JMK:ZJJ:ZHKJHLJZFL**ZNJZZN+ZJMK*ZNK +M:ZJ*ZNKJBHKJR@KJ*RMJZVOKR[O["PN+BXLK*RNK*FO[*VKJ"LJZBNIJ"FKJ +MZJKK:^OKBXOKJZLK*BHKJBLJ*JJKZ^MKZZJJZXOKZVMK:^OKJRHJZNJJ*NKJ +M*BJJ*ZLKJ^OKZZNJ*RNKBRNJ*BJJ"KH*Z@IJ*JHKZ^MK:^MK:^LKZXL+"PM+ +MZZKKJNJ*ZJNKJZNJJNJ**BJ*"FHJJBMK:^NKJJHJ*NHJJROKZ^NKJ^MK:^NK +MJZNKJJLK*RLKJ^N+BRHJJ^KJ*BJJJBOK*ZLJZBJJ*^LKJZJJJJHJZNIJZBJK +MJZNKJ^N+R^N+"^LK*NOKZVNKZRLKJRJJ*^JJZBJJ*BKJJRNK*ZNJ*BKJ*JOK +MZZMJ*XLKZ^LKZRNJJZNKJRLKJRHJ*JJKJRKJZBHJJRMK*RLKZ^MK:VLK*^MK +M:RNJ:HJ*BHJ*"FHJJRLK*RLKZ^OK*^MK"PO+R\N+:ZNJ*NIJJBN*ZBIJZBKJ +MZNKJ:HJ*:NHJ*ROK:VMKZVMKB\O+RPMKZRNKJNIJ*BJJJZLJJJJJ*BKJ*JLK +M*RNJ*BHJJROKZ^MKBXN+*ZKJ:FIJ:NHJJJLJBJLK*JNK*VLK*^MKBVN+ZZNJ +MJZJJJBHJ*JJJJRLKZRLK*ZNKJRLK*RNKJBKJ:NIJBHJ*ZJJK*^MKZROKZVMK +MZROK:VMKZ^LKJZOJZNHJZBL+*ROKJRLKZYM;*XHJ"EKNOH[BX^]ODYO[2ZO: +M<F)*P[\/0ZOB8MJ**@JKF[/3DVMN7B;>+@I#[T\_C\/JXG(R2@NC8]M+BKIZ +MNNM[@V-[BL)"0K*BNNN;`_/#&RO*RD.GWQM.1O9F0IO#,]M[H[/;"AJZRY/O +M\VOZ6DK+>_O+"VL*&DN?)V^*3EYN.Z\;VJZN6FO[.H*"^HN[2@[FYDZ[_Z>_ +M(\IZ"JLJRDJ;[\_SNK[^3QD!60<&&%AH/G+.4CKC)P>K]JAV3I]7-XM^)J:: +M4]/+:[/#ZRX&MDZ_%U?'FXYN:R_#&DZ>[NKW@?%94^C@8,@N2IXN.\-?QWHH +MZ$8Z1XEW\O9VAKH?7_.;&ZJ2W@;FFG\'QU_S^Y/_+^I2_GY28ZD!$6'/R,`P +MH.;KDF+#PX\G(FC(=HIW2>FK=NBH#A\W!]_30J8&QB;B?_>I%^<S"LHK8P/J +MSB8>:TD1K5DF8!`PN&M#/K+S+^<G9GA(/L=)^4?&2$CV6Q<IQV_:9A;6!D+? +M5XEIMUN.<B/_?Z\:_GY^CC^![7&W^)"LP,;_&D[#;[]GFD@8ED^)V4D2>-CH +MB^G)AY(FWM(Z&M)*)RF)5[]BKDL__[.:+DY^FJG!D8&'R``P@'CH]JX?%W>/ +MYBC6@O>)US+(6+@FG]>I]P<_Z]ZVAFI'*5=G#Q.#.W,'-[,FJ!9NJ4$180_( +MX.#X*&@(MCMGYZMV"+:_B8F?QOB8:*8+/\<7U\>;IL:.#Y>I-]]3*[K*D^=' +M)P^I0:V!HJ``H.@VN"`(ZD<_YHAHFA?7+U[VEI:6UN9OZ<F7&V9&SCL/'X<7 +M*=<_VHK_1R?[4UDMK6FX`"!H%KB`6)I7IY:X*`JIM_JF#@*V^%B(+PG)ASH: +MFTN.YK*'B8E'PPN?J2EG=[&-\?)8(#C(^&``!JE'IDAV&H]O7GXS4V98H&C* +MQ]\S3P<'VO:VR@>'_[]GZ0FI1XD1#<'>Z/:66,#`()+GCK;.)P].YJ;OI^8X +M>*@&MB8Z!ZG_PG)JNNYN*J?WEY<I>3&-47<C9_+@D,"@"+8HQI^)9Z;Z7S\" +M5L@(:,C(IJ_/;_\G/]HF3@/#4B)GZ0FAK8W!*0F7J$!`X&!8^.ARW[=_Q\FI +M6^;6:)B@>*B^XNN?QR>;RG,S8C(#)\>YD6TQ68$9YF#@(#`PX,CF6N\GB1GI +M(V_/:.#8^)BXYAOOIX]O)]^J8N]G)S>9T2UAH<$9QJ"XH)!PX#A(5KN72<F) +MN4<>*$B@X'AH5CY[[W_?3W]G'P^'*4EA4;$9P8'3B*B(\)!@(*!(?N\W*:DY +M>:?&EO:@`/@H:*A*)[\?!Q?W?R>I:3E!L5GA@>D^YN:@P"!8H)CHWDOG]\E) +M1P-.MG@@>$A(:.:KBMM_QS>'EVD).0$Q(2&!N3N^_G@`X*"@6,AFBO_'";DW +M9WO6"/B@H$AH:'[+FJ\WEP<7B8EY0?'AX<'Y<TXF>`"`X."@N$8:+P?)>6E' +M0A[V6*!("'CH2NZ>4V?_3]?IZ9FQ$<&!0:'_)F;XL+"`X."8MDIOMSG9B=]S +M(@@@^,B8.`:2_F*_YX_/%RG72;$1@8$QX3_^KKBPL(!@@%C6,I-'N5E)3[,# +M:.#XB!CXYE(FPO]G?Q^7Z2G)05$!(3&!#X:":##P8&#`(*B"OZEY.?=G;T9( +M2#B82*CVII)*+V>'QZGIZ?GQK6'A<2$NMH*8T#`@@,`8)M/'*<F)MXM>]@@8 +M>&@H*,;:&J)_%[>'*0D)@2WQ&7$Q'Z@:EA"0X&"PX/9+9Q?I":G[9L8HV*"( +MJ"B6LONZ[Q?IMW?)^>&M$:%!\9?6[B8PT(!@L&"HZH<W=XDI,M9FUMC85I8H +M=G(+6L-'Z9<7R1E!+?&A<;'O:&*H$!!@X$`@!I_W!U<)AP96-@A8^'8V-@:B +MBWI#Q]>WUPE9$>V!85&!/BC+F%"08&#`V/[7J;\723.(*#9(H`AF)@9F&R][ +M,S?7![?IH:TMH0&MH=96RR"L\.#@8'C2Z5>OMPF*2(AVB!@()F*FQ@N?TUMG +M5S<G1UDM[1D!+>'6B"N@4!"`H"!8)@G)R^>Y#PA(J"AX^-9+HC:RYR=;'Y?7 +M!W_'@6UQB9&MZ?@67L!0<&`86/BJF8GCA^G#Z'CHEDB8%M.2MJZG9S^GMRGW +MS]_9[:T)`:TAZ'C&('`0L-BX2$9IV8?#YX>.2#BH%H@(?@H"/E(_-\=_QZDW +M___9[2TYX9%A=N"88+!0$.`H]H97H8DGW^<+%G@XJ+9H5F[#2YKS9U>77Z>W +M]W^_6>VM>9GA^78@8$"``#``*&,3-RFI%S<;1E:HR,@H=H9N*[L#OR<'1P?' +MQX<GIVEQ+0$)R?D/R""P0%C8@&!&_]<IYU-GJ:/HN$BH1G8H1@,GOR-;)RD) +MEU_GM_=GOVE!\1D'Y^<"AHB`@/CH>-AH9J\W#T[2OP,.AE;V@K.R?KJC+Y^_ +M/V<7]P>'IS^_K^J#"2$YA^<7AS.*EOA(Z,CXR&@HWF(>9EIC*GNO8Y/?O\/3 +M$\H*R[K"*OL[HU,O3Q\??Z?'Z4G73\>I9Z]O[G;F7B@(J-8H-L:HU@[R/L)[ +MFX^?DRKK6PKBXL*B^[/O?X>'9Z=?_V^#@]\IJ:?W":E?!T^FYAXHN(@HN,BH +MUM:&'IXNJ_M#[Z_3[\]O;Z^30X,[F]LS0],OOU_G7Y__/_.S9U<_F[>I_^^G +M8H8.7NB(5HA(Z*CH%CZ^OLL?'Q^?3R\_;TNZ.R/;&T-#K_^G?[__/[_/TWO[ +M.SHNKLN'9_.GJ??_7R^.OHY&Z*BH"&BH**B&WOYB(U._9X>GIR=_CX]O,[/S +MHZNKZRM+DZ^3DR]S@R.+VIJ:4F["(Z??KR=7=^<G#TJ:.MYV=G:H*"AH:%;V +MMJ8B8\]?AT<W]S=G7Z<?$_N[J^I+JMKJV_O[0[,C0W.C.\LJNAHR[F[BTT^[ +MXX>WW_]/ZH+J[K;VMA:H%E:H=N;>OJ+;;Q^'1[>WEY?'AP>G[Z_CFF(:,BZ" +M6@*:BAIZ*AHR0O)NCB[N;JXR@@KOA^>?1ZF7AX?_2TM+#@:&9O:6=M:H]H;F +M?L*+<S^G)R<'MX<?I^=_KY-;JXLK@I(:^@)"DHZ.TE)N+K(::JN*"NKJBKIZ +MZP_'QR>W*:DWQZ>#NRM.MO;V5BBH*"B6!N:FCII+@U.//U_G9V<'MT?G'S_O +M(SNJFGIJ2MJB8A*N4F[.CE*2\@*B&DHJJNHJ8]^'YY]G%Y='AS^[*XH^]E:H +M**C65M9&?M(:NW./'^<G'_^G9R=/,Z-C`]NK2@O#PWN+BPO+ZC+.O@Y._IY^ +MCF+J:DJ+8S-S#[<)2>F7%W<GV[[VJ-8H2+@(J#9FWFZ['R<_SY^GWP\;ZGO3 +M<WO+,T__C_.3#T^O"WH:VC+.'A[.TM+NKEJK"RH*^_/#H]LCP\.C6R?I:9?' +MQV?O"N:HJ*AHN$CHEN:^+OIOAX<?OY^GWP\C>Y,/+WL+0^\OXSO;,S.+XO*" +M@FX>WLYR@@)B"INS`R.S+^]3LZ/;(QOJ6CMG%_<'9V=?PZZV5J@H"+C(Z/;F +M'JZC)[='QT?W]P>?;X\3JUJ"`EKJZLH;+Z\CF_LK2H*./HZNCL[2FBN[6P/3 +MSP_S&V/3P\OK"\N+"@(:[^??3T\_;Z-:)L8&1M8H5O8&'LY"NX]?IR=GA^>? +M#U/#>ZHZ^JM+N[O;,U.O4_/CNVKB4FYN[NZND@)*ZSM;@[.#H_MK"SNK.@J+ +M"VLKZDK*2CJZRLN;(X-CX_O+JGHB0G(NSK[^#B[2(@H+H_.O+^^/[Z]3TS-; +MJZJ*RDKZ:BN[RZN*JJOJ^HHKRPOK:PIJZBO+RSL+JFHZ"FJZ.KIJJRNK^LJ: +M6HH*BNJKZIHZ.KJJ:[M[@[/;V^/CF_NC(TL[R^J*VCJ:(B)BVJ+Z2OHJ*JI+ +M^WM+RPM*>NJJNPO+"RN+>]N;FUO+BSN+ZBIJ"LJ*BMK:NBHZ.LJK*JHKJPN+ +M.RL**^OK*SO["XLJRJHJZXOKBVKJZFIJ:BJ*JRNKJZLKJNN+:ZNJZROK:RO+ +MNPNJZFNJBNIJJRLJB@HJ"@K*^NH+RPN+"[L+"\N+2POK*RM+BPKJJ^JJNDH: +M.@I*Z@JZJLL+JJK+"SO+RTM+FXOKBRMKB@IJ"DI*ZBJK"XOKZ@HJ:RJZNKH* +MNLKKJJH+^WM;HV.;ZVO[B^KKJLK*JVJ:.NK:6FIKB@H+JXKKBPL+JNIKBRN+ +M.SM+.QO;"^MKZRJ:NGJZRMKZ(IH*:VJZ*_O[RSM[&YN;>^OJBXLK2CKJZJL+ +M:HJJJRLK:FJJBDJ*BJN+RRJJ:HI;.[IJ*FN+JTJZJBH+.WN+*[N;*PHKZ[IJ +M"POJ2LIJ:@JJ:LK*J^LKB[N+:XM+*NO+B\NJ*RNK*RJJZHK*BNNK*\K*JVO+ +M:ZKK*\NKJLLJZOJ*:\I*JKLKB_L[ZVJ+:^J*JZHJ*NJZN@JK"RL+ZXOK:FOK +MJJO["^IK"XLK:JMJJBJ*JNKJJJNJJJKJNHHKJVLKRZLJ*JLK*BL+"PK*JRO[ +MR^O+>SLK^HHKRDIJZCJK*BK*:HLJR[O+*NI+ZHN*J\N+:[KK*VHJ:CLK:BLK +MR^N;RROK*ZJ*ZBHZNKIJJJMKZJOK*HNKZLOKZNKK:ROKJFO*.COJ*HMK"^OJ +MZZLK*NL*"@OK*DI+RRNK:VLJZFKKZNIK>ZOJ2^KKZNJJJRLKZDJKJDJKJBHK +M2^LJ"XN*BPNJ*NI+JJHK"FMJ:JK*RXN+J^N+*BMJZJHJJJKKFRNJ:ZJKZJNJ +M:FK*"BIJ*KL+"POKN\N+*TJZJRMJZ@H*"\NK:JLKJHM+:^IJJXLKJ^LKZRHJ +MBVJ*RBKK*NOK*ZKKZPOKJ^KKBRMKR^NJZ^LJ:BJJ*CH*:NKKBKH**BOKZYLK +MZJL[;QL"8D*:"FNK^CLK^QN;FQN[:XL*"NLK(AIJNLL[NDH*RVO*BWN+NSO+ +M"\O["DJK2@HJJR)BRNNJNON[Z_O+*RL;>TN**LO*JHO**RHKB\J+:\IZ2HMK +MBVOB.OL;Z^L*2DN["XK*J[N#*[K+*FJJZBH*JYH::PL+RBLKJGOKRYNK"TKK +M>^OKJFI:&OL#.C*ZRVN**^MJ(JOC"VLKJBNKFY,K(OKZ^OL;BCHKV^OJ2VOZ +MVBO+*[N+>XOZZDHZ^CL+FOI;6\K[JZ(*2WL+RZM*JPOJFWOJFDI+BLMKVLH[ +M:[IK:[K*JOMJ2HLJ.TL".FHJNXM[BRK[RROJ:GM;*@H+JBJ*FGKKZXIJ*BM+ +MR]HBBZ-JVLM+R\.;2FHKFOI;>RK:R@L*>VL:"PL**ZNKBZM+^^KKZ^N+HGKJ +M>BLKZNO*B[M+"\JZ2@O["_LKBLKJBTL;R^J+BMKJJCN+FBN*HBK[*LIK*R/# +MZ_HK"ZMKJ^O:FDL*BP/J@MK+.VOKJRHZ*GMKBLJ:JQL["ZM+.RJJ:VNZNOJ* +MRVNK*FOKZPNKJ\MKZBN+B@H**^O*.NJJZXLJ*ZOKN[MKJPJZB@LK:\O+ZROJ +MBLL+BKL;BXLJRLK*RLH*.DJZ"DO+BZN+RRMJJDO[.\MK2AH*:SN["ZJZN@IK +M2ZLKJ_KZ*[NKZBMJZNIJJ^N[RXK**WN;Z^H+NZJK*ZNJ*TN[*RKJ:@K*BDJ* +M2KHZ"FN+2\LJR@KJ"@I*NFJKZ^N+FV.S,T,#(V/ST_/C^RNZFEKB0E*.3LZ. +M[JZR&KH*ZNO+2]O[JBKJ:NM[HUM+RUO3#_^G)R=G!\<'I^_+PDZFAC;6*.@H +M%@9^KN(*2_._IR<?;R-J&AH:`E)2<F*+SP=WU^E)F9E)J0</"AXV*$@8("#8 +M.`@HMNZ3QRD)">FIES<G`\Y&UBBH]@8FWHZ+YRG)^:'AX:$Y:3<S7BBXV."` +M@.`@&,A&"N<I2?GY.;D)5_\"AM9HR$A(R"CF"R>7B1D!L4'A&;GIWP[HV(`` +M`(``@"`(WML'"1E9H:'9R3</6D:(^)C8V'AH!AK?*7EAL?%!82%9:8/V2%A@ +MP+`P0&!X*,9J5QFAH:&A&<GW8Z96B#B@()B(1DY+1_F!L<%A`<$A5RN>EGB` +ML#"PP(`@>/8OE^FY(6&A^4EIIS+&Z$@X^#B(MFZCMQEA(:$!P:$IQZ<^2!B@ +M@,#``&"8J.:N)\FY";G9^=?GO^*&-A86]L8>FH<)J2FA(?FIZ8F/AD:6N%B@ +MH%B82&BV@DN3!RDI=_?79TMZ.C+N[I)J4S?7!VEYB1?7Z2=2#DZH2,A(^/C( +M:*@F/BXO)Q_G][<_$\]C0@J;@CH/)[=']PF)*==7U\^:`CY6B`C(N/BXB%:6 +MAC*[HP]G9Z=?Y_\3/W_S$Y^G1\=GJ:GW1S<WLTJ*KO;65NB(R`AH**CVI@XN +MJN^O<Q]GGU_'9]^']Y>IM_=I%^?GQT^R>J*FUI;6:&AHZ"BHUD;>G@[*^PJC +MOP^O)P<G!W?7*6D7Z<EW1S<W0X+K/C96%N@(B(@H**AV9B;><DHZRM/O\X]G +M9R?'-Q<I*9=IB;=WE\=;^YL>QI9VZ(AH:.AHJ/;&QM["XAH[;].OWX<G9S?W +M%RDI=^GI!_='IYNKBZ9FMC:HZ*@HJ"@6-K8&WFXNPNH;HW,/IZ?G-_<7*6FI +MJ8F7QT=G#_KJ#H:VUE9HZ*BHJ'9F9J9.LO+B:BL+2R.OST_?9\<W5RD7J0E7 +M-W='_^J[D@8V%E:(B"CH*):&9J8N2DKK8_/C(\-S+],O/Q^GAY>71ZEI-[=W +M1V_K,W*&MC;6"&BH*.B6YH9F<FL:*B\/@U/_;Q//_P]O_Z=GQP<'J9=GQT<G +MN_MCSH8&YM9H5O:HZ+:F1@;"BL(B,V\+XS^_K\\GIT^?YV>'!V<']X=?)X=/ +MBCMKS@8&YA;H%D:65L8>)N9NVAJBBX,#PZ^/3S]_GQ]?W]^GAV>?IP?G/X\? +M#PO*&D)^YF;&]O:V-K;&AF;>#A+BRINSKX^_?]_?'Q^?/X\O4W.3KR_3TZ\O +M4Y-SXTNJ.H(N#C[>IB:F7GZ^#NX2PAH*JJLKBTL[>]M;HR,C(^/#0T/3+^^/ +MST]/#V]O[Z\3,R-+ZAJRKFY.GEZFIJ9>'GX^SHZN0IIJZSM;`W,O;X^/;V_O +M+Z^3,T,#8V,#,_.3<Q-3KZ]S(XNZ@JZ.OIY>IB;>GIY.;A(">BH+>ULC8X-C +MXR.CVWM[FQL;6V,#`X.#8Z-;VYL;6V/C(X-#LS-#`QL+ZOJB,BZ.3K[^/KZ^ +M/K[.;BYRXGH*:WLCP_/3KZ^O+U/3[R]3$_.S`R/;&YO[NTO+NTM+:ZLKJBJJ +MZLIZHL(2+NYN;HX.CFXN+E(RHCIJ"WM;`_/3KZ\O+R^OT_/#@Z,;>[M+RXOK +MJHH*2CIZ.CHZ:FK**BOK:XM+.YN;.PNJBKIZ&N+"\I+24JY2$O)"(OH**HL[ +M6P-STU-3T],3D_/#@R/;>[L+*RKJ:NJ*"DHZ^OJZ2DJZ.DH*RHIJ"LIJJBNK +M*TL+ZVLK*FK*NOJ:>IH:VMH:&OK*ZNM+^]OCPS-SDW,SLT.#6WL+JDKZFJ)B +M@F*BVIHZNDI*2DI*RHKJJPM+NSO[^_N;VZ/C@P.#XR,;N_N+"KI:`D*R<M+2 +M$I+RPN):>KK**NO+^YNC8X.S<Y/S,T/#8R-;&WN["RNJZ@HZ&J+B@L*R0F): +M>DI*BNJJ:\N[&Z.C(R.CHQL;(W.;NCO3.PXNJW-JQN;*.SY&OBHK`GHO/^]# +M#U]/,_./;UOK:WL+@E*"^AKRLII*&B*:BLHKRROKVP.*6EM#^J)C+R/KHT_S +MBON/VQ+JXV(>KKJ>9BYR7OY:HE+*(Z-#,X]_/\]_IR]#;P,**\.*+FI*CFZB +MLCZ2FJX:2KHJBJJ*@TNJ0YO;H_,["[/J+\>;*M>?@C]':Z:?JC8>S@961H9V +MAL:>`IY"KR^;_W=?'Y>WYX?WA_^?_^^ZXHI.9J;>]G8F!K:FSLX2ZZ/#;W_? +M7U]?)W^3[],K.[N:6BI//PXGETX_)\]".C\&/F9&9HCV-JC6-I*V3I-J$X]' +M-X>I5RF7E^D'A^=/KR*BDB:&MH:HUL86]@8>/LXKRP,O?^>?AP?GIW^GKV,# +M^RIB"O)"#X].WY=^)U\;(\)3I@[&AB;(QK;H]K9^1FXK*K\O]W?'Z2DI%ZFI +MA[<G;P,+\GZF1K9V5G:6=K:&YG[RXDL3#U\G!P?'!V<G_\\3FZKZXK(",FYN +M@KH#^TMGDZ-?<P.J>]J^ON:F]C8&%C8&WOZ.*ONOSR?'!_>7E_<W-X?G_R\S +M^C*N7F:&1G8VMK8&YOXN@DMS[_\GYV>'9R??_^_C.RMZDK(R[M+2KNZ2`AKS +M0\O_7[-/'V^S(]O*TDZ^YC8&QC9&YAZ>+KJ[0\\GYX>WMT<'Q\=G7Q_/"RN: +M/EYFQC8V1L8&YC[N0LO#[W\G9V=GY]]/;Q,;RPK"DBXN+JZN0H+R^J(B@^\3 +M[R<?;Q\_KV-KJJX^'B9&-D8V-@8F_HZ:VU._)\?'-W<WM\>'9Y\O[TN"TGZF +MQ@;&1L8&IJ8.8DJ[0[\_WR>G7Q\_+R]#R^LZ.D*2$JX"DH+B^@JZJ\JK^^-O +M,V\GSS^GPS,SXJ[N)D8&]A;V=L:F_D*+P\]G!T=W]W?WMP>')R_3"V(N'J8& +MQL;&!H8>_FZ"BCOCC[^?WU]?3X\OLVNJB^+B@J+:(GI*"VM+FPMK*PJZ"QOC +MP].O[],SDVO*@NZ>)H9&1D;&9EZ.@NL#3Z=GQ[<W-[<'YR<_$P/J\BZ>)F:& +MQH:F7LX2(@I+8Q-OCP\/CX_3`UL[JBOK2HJ+ZRI+HVMK"RL*^OJ"\O(ZFQNC +M+S\/KX\O.VH:4AYF!D;V]L9FIH[Z&Z]?!S?WEY?WQV=?;[-KPJY.7N9F9H8F +MWDZN6LM;L]/O+]-3D^,;&[OK*FHK*ZJ+HYN+8U/;^\.[&AK";NZ:@V-C3Z?_ +M$X_3ZI+N_@9VEO9VEL8>CF(#?R<'=]?7=S=')V\SF[I"\KZ>3MZF_NYN\DJ* +MZVO+2SNJ*TN*RHL+*DLC6[,3<U/O0V/#^ZMJ"J+B`M+N4NMO#P\G!Z=O4_NR +M'@:V%BCHJ)8VYE(+[Z>WUZFI5]<W)\_#"E).?OZ.;DY"ZLJ:"Z.KJVN*FL(N +MKK+N;B**BNNCKT]/CW_?[Y-OXVKJRC*2,M(RXK)R&JKOYR>GAP=/HVHN)C96 +MJ*@HJ+:FSF*#_X?WE]?7=P>GSZ-J8A)R4J[RVOI:"NIJBHK*^IH"LK(R<D): +M2FO[8Y-3+V\/+Y,S@QN+JHKZ6@)B8F*BFCKZVAI*:U,_O_\?GZ^;2I+.)@9& +MQD;&YGZN&OMOIV=GAP>'WP_38\NZXMI:0K*"VAKZ>LKKZOJZZGK:VAJ:>OHZ +MJSL;@W/3KR_3PZ-[R^KJBOIZ2DJBHKJ*.IJ:&J*"@HI#[R]/WY_O0_O*`@ZF +M)J9FAB;^;D)J(V^?W]\G)Q__3W-+ZMJN[BYN+F):&NH+"TM;V]OC6_O[2XJ: +M.@IJJXM+&R,C&UM[BRLJNJ("<K+"@N(Z*^LKZSN;.PN+RTMJNKI*2AJ:"HL[ +M^]MC0\-#0V,[B^OJ6D(2+F[NT@*:2NN;@\-CHYNC6\LKZZIJNGJZ"NHK.TO# +M8SM;XUN[^RL;NZN*N@KBVN):XNJ*.NKJ:KJ+JKM[:NKK:^K:>NMJZGHZ*HN+ +MN]M[.PL[.\L+"SN;RPH*ZKKZRJK+Z[LK*\KJJZHJZLL+NGJ*^AHZ:JLKZFKK +MBVLK"[N+"SK+:VJ;"WOC2TL+"^NKJZK[JVMZ&NKZRJJ*"JMZ*[KKZNL[*CN* +MRTJZBLHJ"JKK.SN+"QL["_O+BPLK:FJJ"NHZ^BJB(CH+JPHKJDL+*QNC6PN[ +M6RK+2KIJ:\I*BXHJ2BJZZRJ*:NHK>FOJ*XLKB\L+*BN+J^J+*\OKRZJ+2VM+ +MB^OJRDHJ>CH*:JN*RJNK*@M+:ZLJZRMKZZNK"VLJZRH**HKJ*ZK+J\NJ^ZOK +MRZOK"FMKJJOK*BJ*ZFH*JDJKBJH+JJIJZVMK*\HK:^KJJXLJ*NH+ZZL+R_L+ +M*VL+:LHJ*^LJ:FJK:VHKZRLJ*RL+:RHK:BIJJJ)*ZJLJ*LLKBVMKR^LKJ^O+ +MZBJ*ZJL*ZXMKJHMKJRHKJFHK*RNJ*RHJJRNKB^JK*NN+:^OKN^H+*ZIJ2FI* +M:DH*:NHK*JJ+2TL+RPL+Z^K*ZRL**JHK*JMK*XMJ*RMKJ^LK:ZJ*"NJJ*BOJ +MZHHJZBN+ZRLKZVLKJBOK*ZJK*RLKJBNK:ZLK*ZOKBXN+ZRNKJJLJZNJKJZHJ +MJJNJ*BKJJJJ*"NNKJ^NKJZLKZ^LK*ZJJ*VN+BPMKZRLK*ZNJJJJJJNIJ:FIJ +M*BJJ*JHK*VMKZRLK*RLKZ^LKJRNK*JHKZRNKJZNK*ZNJ*JJJJZLK*RNKJFMK +M*BOKJBHJ*JHJ*JJJJ^MKBVOK*ZKJ:FKJ*JHKJZOK:XOKJJNKJBHJJJHKJZNK +MZVMK*ZHJJZNJJBKJ:FKJZNHJJROKZROKZ^MK:XMK*ZJJ"@JK*^N+:VN+:VOK +MZZNJJNKJ*JLJ:NKJ*JHJZHH*"HIJZJN+R[O[.[L+:^LKJRKJZFH*BNKJ*BJJ +MJZNK*ZNKJZNK*ZOKZ^OK*ROKZ^OK*RO+:^JJ*FKJ:NHJ*JJK*^OKZ^NKJZNJ +MJJLK*ZNJJBHJJJNKJBHJJNMK:VOK*RNK*RNKJZNJBHIJ*NN+BXN+BVOK*RLK +M*ZJJ*BKJ:NKJ*BJJ*VH**ZNJJZJJ*^N+B^LK*^LK*RNKJZJJ*BHJZFIJ*JJK +MJRLKZ^OKZ^OK:VMKZZNJ*BHJ*JNKJZNJ*BHJJJLKZRNK*NJJJROKJZNJJZNJ +MJZHKN\NKJZHJJBLKBTL+:HIJBBHJJZJK*NJJ*FKJ*NJKBTM+^TO+ZRNKJZJ* +MZBJJJNLK*JJJ*RK+8XLKJQJ:HIH::@KJJJIKB\N+2QN[&_M[NVNJ:HOJJNNJ +MRBL*:DJ*2LIJBBN+*ZN+"RJK*RIK*XNK*ZNKJ^HJJRJJ:VOJJ^I**ZKJJHNJ +MJHNK*@LKZZMJ*VN*:SN*R]NJBSOZJHNZZ[LZZOO**LM*JNO*ZFNZ:NO:2BKZ +M.NI:^FOZJ@L**\MKR]O+&WO+XTL[^_L+:\N*B^HJ:[L;J@.#RZ,;8PMKB[J: +M<L(NSLY.#CX.4I*"FHO+VW/O[X^?_P]_3^\O0X/+BMJ"DNXNSLZ.[B[2@GKJ +M*YOCH[-#XZ.C>\._&QL'@R\G8R=K(].R@MY"QL8F]J:6)C[F+M*+.EL/SZ<_ +M!X>GAV>'WQ^G[S,[Z]H.[GZFYN:F9J8>O@ZN2HK[8]./[T^_SP^/[[/#HULS +M$YL#3_MSCR-SZDMJ$FX>_L;&9D9FQMX^_K)*&]LO'W^G)X<'YP=GI_\_3X/[ +M*TJR/@X>9F;FYF:F_KZ.<HKJR_,O[X__/T__S^_3,S_G8X^ILZ\W[X]">P*V +MYBA&Z$A&J!;V/MK>HV\/7Q^7-X?W]S>?GV=S2]N#"F[K"RYNHMK^3F+NGKYR +MCMXN8E(NHDMJBD/OTQ-_7\\/G_]SXW._IR-#=_\ZPZ?S]DZK]FBHIJA(QGYF +MQE+O2QO?QT>'1Y<WQZ??IV_;R[OKXN+R<N*N[J[R4CX.K@X^3E(2KN+ZZKMC +M$R]/GY\?'Q^_[U,#.RNZ2OO3&^JCKS,*.HIN_IXFQC9FY@8F/BX2.N,#0[^G +MIU\GYU\?WS]OKU/#&]LKFMHBLJXN+@Z.;FYNKC(24O("6KJJ"_L#$U,O;P\/ +M#X\O$S/C^XMJ^NKCF\I+TW.[&QMB4I)NIF;>IF:F_CX^<DI*ZW,/S[]?IY]_ +M'[_O+X\O(^/CRVH*.H)R\JZ.;NYNCNZN[M*"8EH*B[M;DZ^O;X]O[R^O0X-C +M>PN[8^,[&T,3`Z.[2@(2;GXF)B;F)EZ>?L[R6KH+`R\//Y_?WZ>G?[\_S^^3 +M@WLKREKRTM*N[NXN+B[2$J[2,L*"VDJ**_OC`S.O;V^/CV\O4_,CN^L*&NJ# +MX^H[;V^;2_MB[B[.)H:FWN8FGC[.,NHKNU.__S]?IW\_/P^OKR\38Z/C.XKZ +M&K(NKB[.SN[N#FZN4O(:RNI+`Q,3+X]O[^\ODT,#6[LK*T//0VM3_R\+FRLN +M[HZF1L8F9@:F'OYN&JOJ&V__GW\?'S]__X\O[R]S0\-[Z^OJHK)"0G+R<BXN +M4A*NKI)"8MJ:2BO+F^/#<U,O+Z^O4]-SL^.+NBJS4^KJ+\]C:YMZKC)27F9> +M_J:F?GX^DCIZRN/OST^__S^_/P\O+V\O,T,#.ZH*>N*RDJ[N[NZ.#HYN+O*B +M.BJ[H[-3+V]O[Z^3D\.CFYMS3U.[KQ_/.[O+DBXNWL;&)F;&9B:FOD+ZRAOO +M3[__'Q]_'Y_/;\_/+Y-#(TOKREJ"PK(2KA*N[N[N[FXNTI("&LHK.^-S$U,O +M;V_O[Z]S0Q/_'T-C_Q^SJ_M:#BY.AC8&Y@:&)B;>[AJ:FF//OY]?IU]?IQ]/ +MSP\O$P/;BVHZXD*2+N[N[NYN;HZ.[J[R(OKJ"]M#$Z_O;P\/C^^O;Q_GO]/_ +MIT_;NSK.OGZ&=G9&1K:&YJ9.0OJZ2^\_3W]?7Z<G)]]_GW\/+],#.ZK*(K(R +M4F[.SK[^_O[^SBZ2LN+ZJWL#<U/OST]/S\_/?V>'?T^G)P_;BP+^'B9&EG:V +MMK:&YJ9.PCIJ.R^_/Z>'AV=G9Z=?'P\O+^/KRMJR;@Y.'IZ>WAZ>O@ZN@B(Z +MZSL#DR]O;[_/+^_O_Q<)%W]G-R=:WH:HEA8(N&@&9L:^XEO_7T_S/^>/^VM+ +MX[-3H^-?YZ=?)V??;Z/B4HZFQC;&AH8FGFZB*LM[P^_OKZ^OK[/#L[,S\R]' +MR2D_)T=?VF;&J"C6"+@H9IZFTJ.O7R</$X\_LTHJ>UNS\T./!S=??^>?LRKR +MOAX>9K9F_IZ>CN(KX\,;(^_OPR-C`R-C,P.#K\_'B:E/7P</,@8VJ"BHB,BH +M9EX^XL-/W^>?;_]/XVM[DP.*NU,OSP]3+T_/`\KZ^JX^?AZ^[N[NPJK+Z_L# +M,Q.3PR.;HR/+:WL;X]\7M^__9Z_"OF;V]G:HZ);F)MXB&Y,_I]]_IW^3(^/C +MV[MK^^,#8^.S4Y.#6SNK"J(N[G*N[A("VCIJBPN;PV,[FS,S&QMC&PO+>]LO +M?V\#KU.KPA*^IB;FQL;FWGYNVJN[0V\/#[]/[R]3HWL;.^O[8UO;0\/;F[N+ +MROHJFE+B^E(".MJJZBO["_OJBP/+ZQMCN\H[8VK*`QLB:H/KHHHK&MJZHG)R +M6F)2$J)ZHIHK:XJJ0[,J"Z_S"[NS4ZI#_WH*']M.DX].[C_JYJ/S;G*O`V[K +M$RNKZYI+.[(Z&SJZJFO:ROLKJOH:RP,R<@,++HLCPEKSJ^+K>WLK(^O+T^OJ +MVPK:TP*R8\JJR[)C[YHR4Y-^&@^B)IN?4N8OIPY^/Z>^VJ<C'J/GPA[;9RXF +M#[]R+D-/7B['*Y8+J>:6YX_.?A]3!H/G.H9/!_Z2SW^>;O>"]H>?-II'`F;C +M/Q)N\P-2LF]K[MH_R\[#<]H[^YLZ:P,2,V,^<WLZJB)#&@K+NN..XT,>+VKN +MV^J33DK_0KJ;0RHK&Z]RJN/*JJ+;&](+.JNC<LJCBK*S^V:/_PZ^/__.3L\? +MIKN'[@XWVIZJ_P+^ORORJWO2FF_JKNMKZFN2X^J*\XHN\^_":G-3;MM_KK(? +MZG)Z?^X2NZO*F@(ZFR)*:AN+J_IK(_N":]L"+R.F9ZN+J[ICZ^*KCM._QIK' +MSOXG6L9W@]8G;V*2[PIBYUY.Q[K>#VHB[\KN"\<F(G,J@I\Z5O??:+-'AL)W +MABYW)AN/?F^/)EM_ON)?<J;'JN8G:CHJJG,^#^+NTYMB[A,_3B[G$LL;2NL; +M6]J2+_IR&YL"$V[O"TXWQFK'LMZO?U[.WSM>;_O&IY/FX_^.`PXOX_([`O_N +M^P.NHY^^ZK^[BL[ODX9_RBX_[M)?4GI;/J<R(K+O;X;_`]*OHGIK&[NNLN>2 +M'A\[$@OC3K_#AL\O;GKSHXZS$VZ^AR^HAZ^FKVXG4IY'K@*SD[[+KZYOMO?R +MGM_^#[[O\^:_OP9O+Y*#$O_;IB^_GNHOPK.2NN]2:R-NJP\^@C/K,V;3)X;3 +M^T*GCLH_<O,N<Q,^DX,N6T-^2L_*9IL'IN:IGNI3BX]&%[OH%\\6PY^",E*G +M(N;I!AZ7JN8^=XH6?P<&2F=2WF=;9OI';@;'.M(:)UHFA[M^/QO:LM_+QF=K +MOB,S,F)#`VXJ+YX#@[ZOBCX_^R[JVY-NBR>>HB?"0A/[;@N_<LY3DU+"7^ZJ +M#\YO@NK;JII*,R[+BC,2$@<>8B>.&A.Z8RX"3Z*R\T+J4X[_>CJ_+@_#9A]C +M_L\">N.BFWK:+TX+\PX3JJZORT*#VF.R.\..FVM[>FHOLCJC(\+Z+_I:V^NZ +M(XL"H^OR0PHBZZJ;0HMO_HO_\GX/[TX*3PN^PZ]2.FM3`B)CJXHZ,]J*CRX; +M6PH*VN^NLO.*F@JK6]I[2\OZ^^.BX^KZ^ZO"2^.2"J-"FO.J`MMJNQO".\-B +MZF/JZCO*&X-RRN\"LL.J>OK;ZL)KXYJB[^IR#TOR`YMR>_O"NTKBX\I:&XOZ +M*WLZRSM*^^KK&TK+J^N*ZLN:JZL*JRL[BDK[RJHK:^IZZ@OKNLJJJNK+RXMK +M&TMKZ_OK.@O+:VJJ2VJKJBJJ2FJ*2LKJJFIJ:ZMJZZKJ*FKJZZMJJJNJJ\OK +M:HL;2PN[:PMK*\NK:VN+"ZK+:XN+ZPMKZRHJ*CHZ2IJ:VAKZ^KHZ2DI*BHIJ +MZJKJZPLK"VNK2[N+^YL[NR,C&T.#(R,;VUOS@UL3,R,#X_OK.@*NSAZF)N;F +MIAY^#I)BN@L#D^_/3P^/CZ_SLV,;NSL+:VNK:XL+"PLCOS];QT=#QU\?$X(3 +MIH8&J):(J!:HMH8N\HKO/^>GMS<GAZ>?`[L;LB[N;FX.6MJZN^-SP^_OTQ\' +MI]\I!Y^7IW^:&F)6]BAHB+BH*%:&_OHBSX>G1Y>7QV<'C_OK(@[>_IZFSD*: +MBF-O;P\_O^^/'\<'/^D7KY<G3\H.BBA65@AHN%96J&9^2F)#AU^'-Q?')X>/ +M>[JB[B:^OIX.PJJK0P]O#T\_+Z\/?T<G7^F'O_??[]*"+BB6*&@(R':HEB:. +M>F*/IQ\'MY?GW^>3ZUH"#J9NC@XRJAO[+T]O#[^_DQ,/?^??QY<GI\>?2Z*R +M)E;6*(B(Z!86MI[N8JL/G]_'1T=GWQ\C"TH2;KXN;BYZ:GN#+V^OSV^OLX/O +M_R?GQW>')[=_N[KNIM;6J(AHZ-;6MGZ.(@N/_U_'QT?GW[];*R*N#LXN+D(Z +MZR-#;X]OCZ]3`T//WR?'M[<'Y\<3"X+>ABC6:`CHZ)86ADXN*X,_?^='Q\>G +MWR_+BT(NSFX2+IH*:^.SKU/O+Q-S,P^GYS<W]S?G-^^K6N9F*%9HR.AH=A:& +MCNY+H_^G)\?'!S_/[\J"@JY^;F)2@@MCHZ^_[^_/;W/OIR?']P<7Y^?GJBJF +MIG9HULCH:%8V]FZ.*IOO)W]GAP=/+S\*\H(2WKZ:+D(C,X/OGV\O/X\/7R=' +MEX<7=__GTYM^9N9HJ&CH:.A&EJ9^HDO[IZ?G9\??<T^;,I)"/AX"<M)K,P.O +MG_\/_]^G)T>I1[>I)Q^/>ZY&IJCHZ&BH:$9&)DYR(SN_'Z=??Z?S>PN:#KY2 +M_CZ2^DH;#^_/IU]?A\?'%ZFWUQ<__\-ZYL9&:"AH*"C69H8.4@N#,____\\_ +M$_L+HJY.;LZ.TF(J^_.O#T^?IV='MU<I]Q<7'T\#.N:VQN@HZ-:H%B8F[M([ +MD]-_'Q^O;T,ZHJX.7GZ^3BZRJYN3;W\?WX='-Y?I*7>I]__3V\*V1G;HZ.C6 +M*#;F_BYR(T-O3U]_+X^C:O*N3M[^ONZNHBO;@^]_7V>W%]<IZ5?7]Z>3:P*& +M]G:HZ&C6UO9FOA+"^W./#S]/KQ.;:YH"[H[N;E(R.BK[0Z_/?R?GQS=W%_=' +M9Y\3*B+.YL:VMG8VQH8F?BZ2VHO;8Q-3P\-CNVHJREKB8@*R(IJZZ@O;LV__ +M7V?'-_>WQP>G;V.J$CY>9D:VMC9&AN:FSD(ZR\.SLZ]3H[L[JGH:(C+"HJ(Z +MZYM#;W\G!S<7%_?WQU\O&Z).WN9&]C8V-D:&YE[NHFH;\_.O+\/[N^M*2DI: +MVKKZNBN[(Z]/'V>W=W<W-P=?+SN"OJ9F1C8VMD8&)EY.LDI+@Y,3$[-C&VLJ +M2OJB@B(:&DHKNP/OOU^'M_<WMT=G_Y,+PKZFAK8V-C:VAB:>+AJK&[/34]-# +MV\OJ.AI:6IJZRBK+VS-OOU]GQT?'AV>G#P,K0L[>YD:VQL8&)MZ^\GJK>V.S +M,X/[R^L*>AKBXII**DN#TP]_IV='M\=GYU\/8RJR3M[FQK;&QH;FWCXN8DK+ +M([.3<^.;.^N*NAKBFLK*JUO3#_^G!T>WMX?GIV^;RI(^IN;&1L8&AN8>OJX: +MJLM[@[/C&WN+JBH*&GIJ*BK+8R^_WR>'1[?'9R>?K_LZ+IXFAD:V1L:&)MZ^ +MKAJJ"UO#XR-;NRMJ2@H*JHN[8U.//U_GAP?'AR>GOX/JXFZ>)F;&Q@8&9J9^ +M#G*ZB_M;`P.CFTLKZ@I*"JKK2^,3;S_?YX<'!V>G'X^C:F)N?J9FAH9FYB:F +M?BX">BKK.UL;.[OKJJKJBJJ+RUN3[\\?)^?G9^??_P^SB[JR#OX>)N8FIJ8> +M/@ZN8KK*"FM+BXN+JNKJBHKKRUL3;T^?)V=GY^>G/P^3BQJR3EY>YF;FIAZ^ +M;JY">@JJ:VMKR^MJ:LJZ2@HJ"]NS[T\_W^?G)R>G3^\3.SJ"+CX>7B8F7IZ^ +M;BZ2@OHJJRO+.XN+Z\JZRLJ*Z_M#[T^?IZ<G)Q__C]/C:_JR[DX^GM[>?K[. +M[JZ2LB(:&IIZ>CJ*ZNL;,V]/?U^G)Z<?_S_/+P-+"J)RCK[^GIZ>?K[.CBY2 +MDD("`J)*JPM;DV^_'Z>G)U\?'S\/KP/[*GIBDN[.OCY^?OZ^3LZ.[JZ2LN)Z +M:@M;<V^_'Z<GYR>G'S^/KX/[JOKBLJZ.SDZ^OCZ^S@Z.[NXNKI+"V@K+PR_/ +MGZ?GAV?GYU\_#W/[BN+2;D[^?OX^OKY.#NZNKI)"8IJZ*OO#KX^_GU]?7]^? +MOV]S6XO*HD+2[HX.SDY.3D[.;JYR8LJ+>X/3CT\___\_3P\O0]L+BMHR$E+N +MC@X.[JX2PGJJNUL#\Y-S,\-CHYN[RVNJBLHZFMI:HEKZ2NK+6X-#,[.#HTNJ +M2IJ"\I*2$M)RPN(:2FH+FX.O#\^_OP_OTP/;"PJB0K*N;FX.CFYN[E("FBI[ +M@W/O#P^/[Z_3,^/[:^K*>B+"PL+"PL)B&FH+"[NC8^/C&\N+JTJ:6B*B(B+: +MVIH**BM+(_/3K^]O+]/#&PLJ.N+R+BZN[NXNTD):RHLC0W,O[^^O<R.;2ZI* +MFB("0D("@N)Z:FN;@T-SK]/S8QM+*TI:PG+24E*2,L):BHL;`T.3+R]3DX-[ +M"^HZ&F+"0K*R0F(Z:NN;H^/S4]/S@YO+JKH:8G+R0K("HEHZRR,C6V.SL\-; +M:RIJBKH:XB*:.KK*:@OC<_,#(R,C>RK:`H+B8K)"HCJ**BJK.S/3LR-;HUL[ +M"F)B6F)B6MI*"YM[2\N;PS.C2XMKZXJBPF(:^CKZRJM+&_N+*PL;&TLKJFL+ +MJ[I:6CK*NKK*J\N[RXN+RPOKJRN+"PL+BXL+BROJ:NHJ:LJ*ZZOKBZNKJRKJ +MZNJJ*RNJZHH*2DK*BBJJ*RMKR[N[N\OKJZKKB\L[.SM+RPMKJFI*NOJ:FOHZ +MBBHK:RNJZ@J*:BL+2[O[.SN[2VLKZ^NKJ^K*ZBNKJZLJZHI*.KH**NL+2TL+ +M:ZNK:VNKZFKJJZHJ*NO+RTO+ZVH*:HJ*BFIJZJJK*VMKBVN+:VMKZ^OKJZHJ +MJJLKZVN+:RNK*FIJBFIJ*PNJ*JLJ:HK*"HIJZBHJJVO+2_M[.[L[.TMKJJKJ +MZHH*"@IJBFIJ:FIJ*JJK*RLK*RNKZXO+RVN+BXMK*ROK*RLKJJJ*BDK*"@J* +MBHKJ*JNK:NN+ZVOK:^NKZZN+"XO+:\N+Z^NKJZKJ*ZOJ*XJKB@KJ2BIJZBKJ +MZ^NKZZKK:RN+JZLJBFIJZJNJ*ZLK:ZLK*^L+RTL+:^NK*^LK*ZNJJNMKZNJK +MZFIJB@K*R@H*BNHJJJLKZ^OKZ^LKZXL+"\L+BVLKJZJJJJNKJBNKJJLKZRLK +M*RNK*BHJ*BIJ"@J*BHHJ*NHJJROKBXMK:XL+BVN+JVHJZHKJJJLK*RLK*ZOK +MZVL+B^OK:RNKJZKJZNIJBFKJJJNK*ZNJJJJJJJJJJJJJJJJJJJJJ*BJJJ^MK +MBXL+RXMK:VOK*ZNKJJNJJZNK*BKKBRHJJFIJ*BHJZNKJZNIJ:NJJJRLKZXL+ +M"PO+"PL+:VOK*ZLKJZJJJFIJ*JJKJZNJ*BIJ:NKJJBNKJJLKJNHJJJHK*ZOK +M*^LK:\O+"XMK*XJZZNH*ZBHJJJHJJJLK*^NKJROKZ^OK:XMKZ^OKJZLKJZHJ +M*BHJBFIJBFJJ*JLK*XOKZXL+*ZLKJRMK*ZNJZNHJJJJKJZLK*^LKZ^MK*RKJ +MJZMJ*JKJZJJK*JJKJRMK:XMKZZKJ:FIJ*JHKJJNK*RNKJZNKJZKJJJLJJROK +MBXMK:RNJJBLKJRNJ*JJK*ZNKJBLK*ZLJZNJ*ZJJK*BJJJ^NJ:NLKZJHKRTO+ +M:RNKJBHJ*BJKZ^OKZ^NJJZJKJBHJ*BJJJJNJJJJJJBJJZFHJ*JJKJJOKZ^MK +M:VN+:VL+B^MKBXMKZZJJ*NIJB@K*.OHZ2BHK*JNJ:FHJJNN+RSM[FWL[N\N+ +MZVN+:RNK:CJ:6N+:2JMK:RLK:\MK:GH:6J*:.HKKVS.O[V]OKS/#LUOJ&H+2 +MKG)"LC*"FLHJ"PNJZJNKBLHJROH*Z[M[>ULS,QM+:[KZ:BOKJTJ:VGJ*:CJ: +MNBH;<Z^OKU.OSU]_`\JR;DX.CKY>IDZ":KO;.VL[X\.C:[I:(CIK2^OJJ[N# +M4^_3XSM[&SM+:@*N+E+RLO*RVFM#CT_/;R^OKW,#>RIZ"BMJ6K)2+BZN,H*R +M$@)Z"BHK:^NJJTO;&SO[VV.#HSOKBKI*2CK:8H(BFCJJ^^/SK^^/CR]S<V.; +MHZ__G].J`BX./AZFY@;&YDZR2FN;`]/O3_^/@PMJBJMKZPO+:PL;@[.#2XKZ +M(L("`O+2T@**>V-S+V]O;V_OKT-;XX^GWU.J,HX^GEZFYL:V!AX2R@LC<].O +M#S]/+V.[RVNJ*[N;2RN+&]L+"OIZ6N(B^DKZVGIJRYNC0Q,3,T-#LS-#D\^G +MYY_S:G+.'B9FAD;V]L9>4DK[,^]OSY_?G[^O8]L[BRM+&QLK>J*BHJ):&GK: +M8B)ZBBN+NQLC8\,S<P,;RTO;`],/)T?'7Y.J8NX>AD;VUJBHEF8.XNLSCS_? +M)V=GI\^3H\LKB_M+JLKZ2JJ+>WMK"EJR\D)"0L+B^JL[VP-S4Z\SXWM+BPN+ +MZXN[`]_W=^?3FJ[.IH9F9K:H**C&#J++TP]//_^G!\?G?R\CNWM#[Z_+@NY. +M_K[26@IZ,K)Z:YM;0W-CBRHKF\.#N^HZ6MH*.X/CN^N;OT?7%P</JNXF!L;& +M-E;H:"@VWEJSO]^GIR<'1T<'IV\[FL(BRBJK:CK:>JK;\S,CJR("0F(:FAJB +M8H):BCLC`P.CFYNSS_\OJ]+.CG+B*K,/CQ.;"SN;R\H";AYFQ@;F?FYR8OJ+ +M`P]?YV?GI_^/4T/;ZYJRTE(2`GHJBPOKJZO+6QL+JXI*BBKK.SMK*FKK2TO+ +MBZHZ(@+"8GJJ@T]?'\_S>ZK:DFZ^'N;&M@:F[GH[\X^_GU^GI]__CS.;:^JZ +M&B("L@(:BNM+.TLKNB+::NJ*:DJ*:[N;&QN[NQO;>VL*.KH*2GK:6AJ*(S^' +MQV<_XTIRSAXF9D9V%G8&OIICC__?I^>'!V>GS\,+"LHJ*\J"KFXNPOKJBPOJ +M>AHZ*BNZVB+BRENO#P\O,V/;F_N+"MK"DI(R8IHZZZ]G=W>'C^OR_N8&1O96 +M*"B6IF*#OR>'QT>W-T<G#]LZLM*2(CHZVMK*2R,;:VKZ8M+NKO+"LL(B*T.O +M#W^?SQ-C6YN[JJ+2[F[2HDJ*NFM/EVGIMY/R'@8V]I:H:(@HQH+3GR?GA\>W +M-T>G,TI"0AH*RKIJ:_MC\S,;2E*.;BX2DM(NKN+KPV^/4W,SLQ.O<^.+.B(B +M>NJK"AJ"0GI/Z3G)QTK>)B:VJ&C(N,A6CG-/;P^GMQ<71S\J[JXJ8YO*FJL3 +MG^=G?TNNSNY2#J;FIKZ2ZH,SHZ.33W_/K\-+>B*::FH:`MJJBVNK\ZE9&4>N +MAH;F-NB(R#@(IF-OTW,/)V<G9_\R9AZJ;V\CHV\?9_>7)R/:\A)N7H9&MB:B +M6YNJZHOCPR,[2C+ZPR\SFSM;0Z_O`\IB>F).RSG!X4<RABC("`B8('CFK\\_ +MYW];[P>'FQYFIDXJ)P=/SS<I5[?GKU*F/DZ&-B8.<LL/4[KRHAH2+@*:^MN_ +M?^\O\XNK@Q.;"AHNCC=!D9F[MOB@2"AXX'BFCX=WAV)>>Z?#HJYFMB[_QR<? +MA_=7B>FG"I(^AH8FYB9R,[]OFW(F9GYN[J)[K_]?3[O:FHHKVWLK6V.[Z9&M +MF8)HX&!(J)@@B'J?=]?[=L;;SZ/K#A9&RZ?GY^>'EPG)-VN.IJ:.0E)2"L-# +M"W+F-@8.&BJ+>P.O+R/JN@LC.^N*XB**FXE1;2&NN`"`2):X(.B#9Y?'W@B6 +M.Z<_@PY6]NH_G^=GMRG):7]"TJ*B\@[^PA._8W)>9N9^#H[R:IN#`^.CHWO* +MXMH*ZJ+Z.6T-V19@<.!&DFB@EJ=W]_M(6+9'Z8=Z-FCVREM[/S>)^;E'4@:> +M@LHJ"ENGQX_NQL8>@DKB4D+ZNGJBXLIKJJHK@K[^XLEMO8$H`'#@WNHH("CW +M"9=RF""&:4GGIF@(-LJKTC.IF:&YST:HAD+JB^._QT>;AI9F8B]OJ^XNPMJ: +MFAJK,_/J[J9F/@F-O>%HP/#8LB(((!:7"6?&V!BK>4F3%LBH;MOB;K\)&?E' +M/E9F:]LR$LO?-X?:QB9*0V,Z[NYZBYHR*_-SF\)>)AY"&0V-J9C`0`BKWOC8 +M0HGIJF@8J'>A5WYHR';R@NX+U]DA^:.(^"CNPYM+CX>'+XZF@K]G3X*FWE)Z +MJJ./3V..!D:.H<UM9QA@8&A.B."8DPDWWDBXLDE99\:6AG[^=E:J.8&AIX;6 +M!K)2!H9CEY?OO@9:YP>OHG***Q)F9J)?9[/N_G\QC<&&&'A(YC;@`,@_UP^F +M*`:'B7>R!EX"/C86;M<9N0<[&B("GO:V@A_G;XK:@^?G+[I:JGN:;IZ^VD.C +M(NJYT9'7MJCH]KZX@"#V"@NNQK8SJ2DG&I["*^[>?M+31[>GTQOJ:J*2<NN3 +M#V\S&],/CZ_3HSN[^JXN$G(RXF.I^7>BPY\+&ZOVB'9F%O:&M@8NFKI;KX_/ +M;P__CY,O\\LKRE)RJ@OZ&DHKP].[RDOS;X]S2^MK"^K:PB)+!ZDO2U?IIS\S +MWB:Z7F@HUM;&YG86ACZB(U._7Z>'!]_O;Q-[^PN:8F)BHFI[(Q/OCR\S\Q-[ +M2OK:TFX*9X=:4VG7_^>O_G([!NB6%M;&!I:VGFX"*NL;[U]G)\]OCW-C(^HB +M2BHK8_.;>_-SLY.30\/;ZN)R$KNW!_K?";?3OTJ&+OH6:'86UL8&]N92&NL[ +MB[/?YQ_OF[O#HZHJ2]L3[^-K2_OC[V]SLQ.#&\LZ,GK_UY^RAVDG@^\RYLI: +M*&CV%E8VEJA&[DH+*QNGM^<_+V,3;YO:2@N[&SL**\.O+V]3PS-3`WM+"\-' +MU^.;*:G#HUL>IH*VR"A&]O:VEO:^^BIZVA/GIR]#.Z,_CTJ:>Z-;8TLK<\^/ +MCV_3KU/C^PM+7U=?:O>)7QM3$F92GH@(]G:HEA86IAJZRFLO9^?O@[-CH[M2 +M#@I;*^O;PW^'IV^_G\\O8PJ*#Y='N_]IEU,3:Z8>#E;(J#:H5O86!E("<EH; +MO]_OHX-S\]O:TFI#>ZH[@V]?WX_/_P]3DZ-S)W<W(T=YJ3\KKGZ>1IC8*!8H +MZ#8>:Y\#HF.'/P*.>B+.)J:.>J)RF^>W9^>W=X?O@Q-#8ZEA&=\WR1>F5I:H +M*#C8.*@V*+;+)Z]KYS=#WCXRTIYFWDM;4@[[+R/+[V?'WP__IR\+VP^?5V%A +MQ]<Y1S;H1FCXH-AHJ"C6XI^/,S_7]P)F0M)V5B;NTFX2`P^KJY^'IQ_?Y]^S +M6P\_C[?A`1>7F:E>*,:H>*#8:&C(J!I/*PMGU\<:?OOZUE9NKF8>REMJ0B/G +M)\^G1^<_CP\_[\_)P7D_^7FK5B8F.%@8B"CXR$ZOJZK_EQ>C#F-JJ%9";C8F +M*AOB+ING;X,G1Q^_7Q__?W_7(2&G:5E/-EZNB%AXB*BX2*9[`HZ?E^>ORR^+ +M]O;";E;F&]K.<O.O:T-GAR^_AR>/#V=I(9GG^9D*9@J.^)B(:`AXZ`Z.WCOG +MG]]?,_L:9F8NYO8.FKX."^.;0]]GIY]GAS]/)_>Y6=?7&>=>0IHH>(CH:,B( +MINY>@C^_SZ>/6\N>9NZF]J;"3GZB:\O[[Z=?OR='7_\'MXFA";=YJ6[22G;X +MB.AH"`C&TOZN;]\_#T.ON@:FDF9V?K+^+JK+"P,?Y\^_!X<_I\<WR9FI*3G? +M4DLN:+CHB`@(Z&9^'HI?;T.'YTIBBLXF)J:>GK["BIH+C\\//U^G']]?!U<Y +M.7?)R=M*.Z;(""C("(B6)J:N,]^/?V?SZS*>_N:VYLZ>_JIK*U,_GQ_?YV=? +MWP>7";FI:<F_>B..:,@H"$B(J`;FSAM/C\^'_TKKPJ;>'F9F/LX2NJJ3OS^G +MYR<GY^=G=\G)5XF);TLS3NB(Z,A("*A&ALZ+;^_/QY^JVTH^GAYFAEY^4EKZ +M<W^?IX>'9X=G!ZG)Z7<)UZJCNX9H*"C("&B6!N;R@Z^3)]_;6_HN#OY>WCY> +M#F*RZ^\/_V=G!T>'QU<)"5<IZ>]*FTZHZ%9HR&A6M@:.RP.O_\^3XS+NDCXF +MGLX>3H+:JY,_I^=GM[>'Q]=IB2DIZ1\*^\XHB*B(2&BH=@:.JEN3GV>3V\.N +MOBX^YIZ./E*B^N-O_U]GAV='MW?IR>E7:8<JFT)VZ*AHR(@H=L8>H@,O;R=/ +M`[NRKCZFYMX>IBYB6ML/_Z<'QP='M_<I"6FI:9<CHZO&Z*CH2`CHJ)9F<BK; +M[]]OX[,:+G(.)IZ.GL[:&BL3/]\G!S?'1Y<I"8FIB1<;PYO&:%;HN`@HJ!9F +M[GH[TQ]/<^-JVG(.GGY^'@YR@JM3SY_G!\='-_?7:0FIJ2G/RT-NUJ@6",CH +M**BVOO*KPU./KQN*2L+.3@X^?F[RLLKC+\^GQP>W]_>I"0FI:>DO\U.>J!:H +MN`CH:"C&3M)J\S]O,^^J,MIRWGYN7IXRLB(CSS^GQT>W]Q?I"6GIB7=3O]N& +M5O;HN&CH:*CF/H[[#T-O/VO::X)>SNZF'E*N4DO3[Y]G![?W]]=IB2GI*2<O +MCT)&-O:(B"CHZ#9>_I)[[\.33]LB*DH>'BY>YBXR;JKO;[\'1\=WUU=I:2DI +ME_]OL[[&QI9H*%8HUH8F3@*J8T.S^SN*@JYNSDZ^3BZ2&OMS;]^'QS<7*>EI +MB2G7AW]SDB:V=BCH*"BH1N9><MH+FT.;JVN*8JX2CL[N4JY:NV,OG^>'MW?7 +MJ>GI*=?'/Z\Z'L;VJ.BHJ%:V)I[2H@NC@TMK*]K"LJX.+J[NDAJ*FZ]/WV=' +M-Q>I*>DIU[>GCRH.9K;6J*BH5O;FI@X:RBN#&TJ+2T)R6BY.PH)N`NNJF\__ +MGP?W]]<IZ2FIE^?_(]*FQI:HJ*BH=H;FGK*:"H.#^BI[(JXZ8LZR.J[R"PMK +M+S]/I[<W=ZGI*:D7AW^3.OYFMA:HJ*C61N;>;H**BSNKJVL*HN)B0G*"@B** +M.QLS;[\?YX='=U>I5Y='9S];PGZ&]A96J-;VQN;^KJ(*^QO+:\OJVEHB\D*B +M6AHJ.QM#;T\?YP=']]>I%_?')X_K4MX&-G86%G:V9MZ^4J(J&YL+NTL*(B)" +MTK*"PJ(JNYL#+T\?YX=']]=7%S?'YP^[LGZ&MG;6UG:VAJ:^KEJJRPM+2RN* +M^J("0D+"XIIJ2R-SC__?)V>'-Q<7]T<')X^[`C[FQO:6EO:V!B8^+L+*"XL+ +M.\NJZLJBXN+"`MK*JSOCT\^?IV<'MY<7][?'Y\_;&@ZF!K9V=O:V!B9^#O+* +M*RO[&^OJ:AH"0L(RPEJ:*IMC4T^?)X?'-Q?7ES='Y\\;(K[FQO86%G8VQN:> +M#K(J.\O;@_OKJ_H"8@+RPJ(::OOC4[^?IX?'-Y<7=[?')V^[`K[F!C:6EO9& +MQB8^+N(J^YL;&TOJNMI"<G*2\B*ZJIOS[S^G9\?W%]?7=T=G_V/:;J;&-G86 +MEO:VAMZ.PNH;HV/#VXMJ&@)",A+R8EH*.X.O/Z=G1W<7UQ=WQ^?_(QKN7@:V +M=M:6]D:&IDX":SNCKQ-CX[OZHN(2KO)"@KJKR\,/'X>W]Q>I5_='YX_+@KYF +MQK9V=C:V!N8>SK**NR-#LV-;.XHB`D*R@N(:JIL#+Y]G!S>7UQ?W1^=/6]J. +MI@9&]G;VML9F7KZNFFO;0S/#0X/+2CJ:XF(B6LH+VY/_)V?']Y=WM\<G3^/Z +M;EYF1O;V-D8&YAZ.\EJK&R-#$\-CHXOJJLJ:N@K*J@M+DW\?7\?WMT<'7X\S +MZJZ^WF:&AL8&YEY^CI*""CL[^Z.CFQL[JXN[JHHJ:BH+.QN3OQ\?YP>')U\_ +M\SL*P@Z>IN;FYN8FGDXN`AKJFZ/;8R-[>SNJBNK*.HKJ:BN[@V_/SZ>'YZ>G +MO]/#:\*N[KZ>WJ:F?KX.KL):ZIO[R]M[ZRNJ2DHJJNKJ*JJ+"[L;`X^_3W^G +M7_^_[V,[*H*N[D[^_GZ>/HXN<EJZRNL[2[L[RRLK*ZHK:RLKZRLK"QNS+R^/ +M?Y^_SV_#&TOZ\I*N#@X.3LXNTI*"&KJK2XN+^YO+JJIJJXNK*HO+NWM[FR,# +M@P-#<_-#,_-CVSLJFEJ"<G(R<O("`K("(EHZBJKK"XMK:VOK:VLKJJLJZBJJ +M:YNS$U/OCV\O4X-+*XJ:HF+"DM+R$I)"`B)ZRFHJ*JKK._MK"_N+*\N+BBMK +M*JO+ZRM+^SM;P\-#$W.#(WOKBDH:`L*R,D)"0@*BVGI*RBJ+2SN;V[N+2VMJ +MJ@NJ:HLKRJK+*RO;6Z,S\[/S,^,;2ZL*>B)"\I*2<G(R`B*:RJMKR[L[._N; +M>SL[.\LKJZOJ:JJJZJHKJ^O[&UMCL[/S,V.;2ZO*FF+RTJZNTC("VDKJ:PO+ +M6QL[2PL+B^NKBHHJZNJK*ZN+NSL;XV,#,T-C@UN[:ZHZVJ)"\D)"0F*BHIK* +MZJL+2SO[.\MKZ^OKZRNKJBHJJZLK:^N+^ULC`T,#(YN[2ZMZVMHB@H)B8N)Z +M.KKJ:XO+.[O+BZOJ:FJ*BFHJ*^OK*^N+B\N[>]LC8X-CHSOKZDH:(F+BHJ+: +MNFJKZXN+"\L+:^LJ:HH*2KI*"@IJ*VNJ*[M+NYO;HR,C(UN;NRMJ2IHB(AJ: +M^LJ*BBHKJ^O+RPN+:ZKJBKIZ^KI*"HKJ*^MK2WN;&Z/CXR.CVSN+*KIZFIJ: +MFOI*"@J**JMKB^LKZ\LK"NKJ:NKJZBJJJ^L+"VOKZ^MK2[L[^_L[R^LJBKJ: +M&IIZ.@IJJNOKZVN+"\N[NTO+:RLJBDJZ2LH*:FKJJ^MKBXL+B^N+"\O+"\N+ +M:VLK"LHJB@J*BFJJJJHKZZNK*RNJ*NIJBHJ*BNJJ*VL+2[O+R\N+ZZHJ*JLK +MZ^N+B^OKJRKJ:HH*RLH**NO+FYL+:KJ:6CJJ:PN[N\L+BRLK:VL+BRNKZHK* +MR@IJ:BJJJRNKJZNKJBKJJROKZVN+R\M+N[L+BXOKJFH*2DI*2KI*"FIJ:FHJ +MJRN+NSN[N[N[R\L+B^NKZFJ*BHIJ:NJKZVMK:^J**HH*:FKJ*NHJJBLKZ^NK +MJROK:PO+R\O+"XOKJBKJ:HIJBHHJJZNK*XOKZZNKJJJJ*NHJ*BHJZNKJZBJK +MJRNK*VL+R\O+2PN+:ZNKJNIJJFK*:HIJJFMK:VMK:XOKJNJ*"@IJZHIJZBJK +M*RNKJZNK:TM+2PMK:XL+BRNKJBKJZNJ*:BJK*^LK*^LK*FJ*BHIJ:FIJ:FKJ +M*JJJJROKRSN+RWO[NSO+B^NKZHK*NKJZ2HHJZBHK:XO+RXMKZZLJZNJ*R@H* +MRHJ*"FJJJ^L+N_M[FQN;.[O+ZZIJ"LIJ*FJ*ZNKJ*JHJ*BNKJBNK*NJ*BJIJ +MR@H*"HH*ZJHK"TL[FUNC(R-;FTOKJFK*NCJZ2HJ*:BJJ*NKJ*BKJZFIJ:FIJ +MZBHJZNKJZFJ*"LIJ*BN+^UOC@P.#8R-;>\OKJVI*NCJ:XEKZVMIZ^DJ*ZJOK +M:^MKBVOKZXN+*XN[RXN+Z^IJJBIJ:@HZNLI*"JL+RSN;6V-#0\.#(YM+:^KZ +M&B*"PL("@B*:.LHJ*VOKZ^OK*RNJ*JN+*^N[^YL;>_M;V_O[^VOJZHKZ>OI: +M(EHB@F*BVOKJBSM;0]/O;^^OKY,#6TN*VF+RKBZNKJ[R@J)ZBNHJZPM+2SL[ +M"XO+"XO+2PO+F]O;6YO[.PMK*FJ*2OIZFAH:VIHZ:BMK"TL[VR.#P[/#8Z-; +M^^LJ"AJ"8L)RDC*RPB(:>@JK:RLK:\L+2SL[2[L["^OKZRN+BZNJZVNK:TL[ +M&]NCXR/CX]L;^[M[&[LKJZJZVB(R+NZN+NZN<C(">HJJR]LCXV,#`^-;F_N[ +M2PNJBDJZ.CJZ2@KJJPM+2SNC`[-#0P.#XZ,;>WM;XQM+>_LK"AI2#HY._GX^ +MS@ZN0H*B2BO+V_.OKR]O+U/3D\.CFXN*.OH:HJ(:>KKJJJL+FR/C@X-C(UL; +M>[MKZYLC>\L[^^NK*AJ2KNY./DY.3H[2LL*BBLL[8Q-3KR^OTU.30R/;2RLJ +M"CKZRHJ**JJJ:[L[._O[.SL[2^LKJ^H*NCK*ZHM[>[M[@P.C>^NZHN*2#CZ^ +M3HXNTA*R&FKK.]MC,U,OKR^O,Y,3PR/;NVNJ:LHZNLJ*:NKJ:NJJ*RMK:VMK +MBXOK*RLJB@J*"HHK2\OKBZ-C^XNKBCJZHE(NTG*2\K("VKI*2NKKRSN;&UN# +MPT.S,_-#@X-C>_M[RPN+ZZHJZ@H*BHJ*:BIJ"@I*.OJ:6EH:>GJZ*FN[>YM[ +MFR/C(Z,;^TLKNB("0G+2$O(RPF):.FJKRWM;XP/#0S/S\T,#X]M[2VOKZDH* +M2IKZRNKK*VL;&VKKRTHBVLKZHB*ZNIJB^@IZNILO4W,/G\^3+Z][>J+R3AY> +MWJ:FG@[2LDI[PW./_S\_/_^/TS/;ZMHB,A(2<K)B&LJ[VUL#\S-#`V,;.SOK +M*BK*VDKZ,J(:8@(:>FH3TYL/'T/##X/:"GK.?MXFYF8F?KZ^8BOKXT^_OZ?G +M)R<GWS_O`Z.*`L(23LYN3LZN\D(:JJO+HS,3KR^OKS,S8SLKZLK:HN*"`K(B +MJAN;6R]3XW/S.ZLJ>A(./GZF)IY^_F[R@CK[@U./?U]?IR>G'W\/\P.+>N+2 +M#DX^GOZ^3NZ28OIK8U,O#T\/3V]S\UL[BRJZFN*R`D+:.WM*K^^+K]/CRZMJ +MLNX^#J9F7B:F'NZ26HL#+V\?)R?GAX?G)]]/$^,+6M(._B;FYN;FICX.TOKK +M&_/OCS]__Y\_3P^OLZ-+ZNIZ`@)"8OKJRNN#V[OC(\LJ2AI2C@[^7EY^GCZ. +MD@+:BZ-#+[^?7R?GYR>GI_^/[WLK.E(N_MXF9N;F)EZ^CG+Z*@/3[[]_WU]? +M?__/+Y,C^VHZ6C(R4A(:ND*K(SHC6YM[.OMZLC*NCIY.?CY.;K+2NFL[8Y,/ +M#S^?7]\?'S__CV]#.^LB`NZ./AY^IMZ>/LZ.DC)JBQMSK\\_WY]_'\^/[W/C +M.^M*XC+R[JYBVC*Z>_J+.[O;BJ,KVOH"LHXN[@YN+L*2VBJK>UN3$Z_/3[]/ +M/T]/#Z^O(\OK&H(2;DY^GMY^_KZ.KL+:*YO#KX]/_Y]__[\/K\,C.ZM*HB)R +M`AJBXAI+2NJ;*[M*:^JR&O*2[BX2;JZ2`@):JJI+V[,34P\/#P]/SV\/+[-S +MXPNJ^J)2;LX>?IZ>GCYN[K*:BULSC\^_/Y__3[]OT[/CNRM*6H+RVF(RB@I* +MJXO+JBHK.H+BLJ[N[BYN[K+"@GKJ*\M;LY,O#T]/3T\/[^_O<UN#>SK*VK+N +MCBY^?KY^/DXN+O+**_LS#\\_WY___[^/D[-C*ZI*`AIZ>B+ZZJ)*BLH*FBJ: +M,H(24HYN4FX2PN*B^BMK^V.3KZ^/SP\/#X^OKZ_3LYO[*WJZXM)N#@Y^GCY^ +M_@Y2<J+KVX/33\_/G_]/#P]38R/[RVKKB\H*^ZJZ>_JJVN)J#I)NOD[>#OZ^ +M+G):VKM[VY.OSV]/?[\_O[^/4]/CFWM+*_H:(A)N;@Z^/KY./@ZN4D)ZJLNC +M$^]OOW_/O[]O[W/SXZ,CX]MJ<VLZ@X*+LJXZWFY^WI[FOEZ^#JZB@GM;PV^/ +MG[]_7_]_/[]OTY-;B^H*2J("HG)2\J[N+JZN+E+R<O(B&OJK^UNSD^^/+T]O +MKR_SL]./L[-O\UL;H^J:8D*.7CZF9F;FIB;^+A+BJP.S[W_?7Z<GIY^?_^_# +M6PO*(C+2+NZNTJZR>J+Z*JOK*VNJ"LHZ6F(B8F+Z2BJ+NV,S4^]O[^]O?Y^O +M/W^#0R,[@A)2/J;FI@9&9B:FGM+:>GOO3T]?YR>G)Z>_[R\#ZJ)B$LZ.+HYN +MLMK:BGNC6T/3D[,SPZ/+2XNZ^EH"$A(2+E+2\K)B2HHK^^-#LZ^O<_/SPUM; +MHUNCL^.;KVM[8YHK,L(NOHZ>#OYN,JZZ"FN;@Z^S4U/S0YO;N^HJ"LKZ^LJZ +M"BKK"[NCXX/#`R/[NPNJBDHZVJ*B(F(B&GJZZJHK*XN[N_M[.\O+RVNK*BJ* +MRJJJ*LN[ZSO[*RJ*VB*:@F)"0EJ::LH+(]L3[[^?OY]_CS.#^\(N+IZFIMX> +M_JXB2@MC+Z\OSV_S6WLJHF(RKBXR6GIJ^\-S4X^/+U,3X\NJ2N+RDC(RLEJZ +MRJI+>SN[>QO+*^MJ^IH:HB+:NLKJ2QLC(V/CV_M+*XJZ.GH:^DIJJHL[F]L; +MFSL+ZRH*2KHZ^KK*BFHJ*XL+RPO+B^LK*@I*NKK*:BJKZPM+NTO+RPMK:FJK +MZBJK*^LK*RLKZRNKJZIJ2KI*NHJJ*BJK:XN+BPL+RXMKZZNJJJNJJZLK"PL+ +M:RNJ*NKJRKK*RHHJJBHKJVM+RPN+:RJJ*FKJZBJKJNO[2^LK*ZHJ*FKJJBLJ +M*BKJZJNK*ZNKJZLKJNHJ*JJKJJOKZXOK:XMKBXN+"XN+:ZNJZNKJZNIJ:NKJ +MZFIJZJJKJZJJ*FHJJBKJJJJK:XO+RRN+RVOKZZNJJZOK:^NJZNHJJJHJ:FKJ +MZFIJ*BJK*ZLKZ^OKZZNJJJJKJZLK*^LK*RLKZ^NKJJLK*ZNJJBKJZJJJ*JHK +M:VOK*ZLJJHN+*DK*"^N*ZFJKBRIJ*NL+JPIJJJNK:JJ+:PNKZ[O+N^MJNZHK +M*GH+"JHK>LMJ*JL*:ROK*ZJK*ROJZZHK*XHKZJOK*JNJZVMKB\M+RPLKZ^LK +MJVJZ2HJKBDJ*ZHN+ZZLJZPMK"NJJ*ZJ**BKK"RLK*PN+*RKJJJNJBHJJ*^NK +MJJJKZRNJJ^MKZVOKJZJJJZNJJBHJZFKJ*BHJ*BHJJZNKJZNKZ\OK*VLKJBHJ +MJROKBXN+Z^LKJZJJJZNJJZJK*VLKJ^J*BFJ*BHKJJJLKJROKBXL+BVN+:XOK +M*RNJZHJ*"HIJZBJKJZNK*VN+"XMKZRLK*XOKZJOKJJJJ*NJJ*^LKJBIJBFIJ +M*BHJJJNKJZJJJROK:XL+BXN+ZRLK*RLKJZNJ*BHJ*BJKJZNJJBKJ:NHJ*JJK +MJJNKZVMKZRLKJZNJ*JNJ*NM+*ZLK*ZNKJJNJ*RNKJRHJJJJK*^MKZ^LK*RNJ +M*JHJ*JKK:VLK*RNK*FIJZFIJ:FKJJJLKZXL+R\L+"TO+BXNKJHIJ*FKJ:NKJ +M:BHJJNOKJRHJJZNJJZNKJRLJ*JJJ*JJK:^LKZ^LKZ^MKZ^OK*RLK*ZLJZNJK +MF^]S(CX>;HKSKTO*ZWN#VZO:&OO#XXNB<@*K(Z,;"ROK"VM*(N)Z*YNC>RKJ +MJRNK"KJ*:QN;Z[I:VLKK2PNJRDH*"@J**[N;&[L+JXIJJFO+RTN+BXOK*^K* +MZBO+.VNKRKI*"JNJJZNKZZNK*@HJJVLKZHHZNHJKZVJ*BWM[NXOJ:JKKBXO+ +M2POKJJJJ*BLK*ROK*VJ**JOK"PNJ:NHJZFKJ:NJJJZNJ*NHJ*ZLJZFJ*RHJK +M:\N+JRJJZZNJJBOKBSL[RVNK*FJJN_N+:XLKZPLK:@H*BFIJROKZ2FJJ*VLK +MZXL+BZNJ*NKJJVLKJZNK:LK*2HJJB_L;&_L+Z^MK"SM+*VH*BNJKJZLKBTMK +M*IIBHDI+>Z.;JLKBXOIJ"QLSP_OZ<M+B"T-#RQI"0GIK6T-#`V/[JPJZNJI[ +M&SMKZ@K*ROK:^JH[.ZO*.GI*JSM[BXJZ2BIK:RK*RFKKFS,38RM:LL)*^Z.[ +MJJHKZPLK2LHKRTL+JVKJZPL+2POKJLK:@B)Z2JK[XV.;N[L[F[NJ>B+:>HJK +MZVLK*AH"8AIZ>OIZ.@JJZ\OC$Z^OTP-+*FJJ^_/36PHBHKJKZAKB0L+Z.[/3 +M4^]3:_(^GC[2BFOK*ZOKNZ-;>WNC@Z.+VJXNPBJCPWO*PBZ.4OK+@Z^/[Q,# +M^^JBPEKK\R\36SL;XZ-KVD+:*TM*KLX.[G+*,P=IZ?_^J.CVDC,C*CKZB@L+ +M`JXZ\Q_G_ZI.WC[BVZ_SH\OJVJX^/F+3)X>G$XJ"8AKZ.NI;$]-;2F*Z0X^S +M:C+"(DJKZT-CTL96-H(IH?E?AFCH!CNSVJZ:0Z_SLH8FB\>IE\_.-G;F$INO +M#S\/H]+F!IZ+7T>'CRJ24AH+^QN3#V\CNA(2:B_?'Z,.AN;2XV^3*[(._KZ. +MDJ(;-[GYZ;+XH`BJ!R=KGH[[/\,^IB)G*==OQF@HWD/?)Y_O,[K^ML8RGY?W +M3UI.KGJ;0Y-/7W]KW@8^LR>GTTKRKJZNDCHCCR^K[J8F/MJ+2EI#%TFINP:6 +MAN*#NGZ.^\\3&LYN6R<G+_K.YH8F?C+C_Y\OR\+N0BMC,]/O#^\CJPM3G_\3 +MB\H*:DK"0BMC.R*NKJY2CK*W&?EGAG@XMLX&*`Z'UX<R1B9C!V]JHQ_G6^86 +MYH-?S]L+@SL.QL9"3^<GWU^?LP+NJX]O(]NC&YO+ZHN;.PH:.BNG*<?2!J;> +M=B@69K++&L[2F^-*RD-_I\\*DNM#2I+JPQ,#*V*:"ZH">J\?OW,#C[_S(SN: +MJH,KDKKO\\JKDS=)%VZ&,J[H."@&YMY.`ON3*Y(+#\,Z*Q/SZR+R2ML[Z[/_ +M4QHB:XNKVZ_/G]]/$],OVZI[6Z/;:SOSOX>7!YI.KD;(2!;VJ`:":RN[LW/O +M;^,CPRO2CD(B\EK[;[]O,\.C*HHC`SO#C].OW]^/SU]_PX]'UQ=_.NIN*$AH +MULC(!LY^#@O/C^^O+V_[TKYN;IYN"\-C+Y_?SU.OC^_C^Q-OLS-/'S\?Q]<I +M*=<_,XJVB`B(N/B(-H;>NH^??S^/TTNN?D[^YAXB"DH#_Y^_?R>?TT./;_/3 +MCY]GU^FYF5>'=XN6Z"CXH)A(B*@&XH]OW\?GDRHZ?H8&AB8>SH(C;V^G1V<G +MQP>G?Y\GQS<723G']^G;!L9&N-@X2`AHE@Y;"R]')W.CXU+F9F9F!N:.2@KK +M3Z?_IP>'9\>7Z2DI>3DG=ZEJAB;&N#@("&CHMA)KJQ\'(W,S#J9>!G;F)N;N +M(CK;#[^G9Z<G)X>IB6D96=<):1N^GO:8.#AX2`CV;N,;1^G/KV=KMN:FJ*C& +M9F;^XGMS[V='IV>7%RD)22&YMSE73H9N*"`XN#@X:"8*F]OIZ4//MP)6'E[H +MZ`:&1A[Z6R,/Q[?GQ^D)"7F!.9>AJ2Z&C@C@>-B8V`BV0F-;Z8F'CS>3]@9> +MU@@V)L:&0F.;4V>79\<I"0FY@:''V;E:1I*68-@8&*#X]F[CFNE)IV]7CZAF +M?JC(MN:VYL)S,\\'%\?':3GY^2'9R<GW@UXVN-A8(*"8"*@RC[_7:4<_9PJV +MMD;H:/8V!CZZ8_^'M]?7*0GY.:$A"3F)O\XFUJ#86*"@.%8F0]/7Z;>?)]OV +M1C;H"!:V1K[BLS^'MZDIJ0EYF5DAR4EI3[[F%J"@V*"@N'9^0Z^I:6<_9PJH +MMO:(R!9VMCY:+R>W=VEIZ4D9F5E9"4G7>V8&:"!8&!C8:"::[R<I]Z?O0R;6 +M=BAHZ/8VWB[JSX<W%VEIB?E9H2$YR0D_SC:6V"!8V!@X1I*OI]?WYW\K'O:6 +MZ.BH%C9>$GIOYS=W*6F)N1FAX9G)N0=N]G9XX*!8&'A6[N_GEY>WY^O.AO9H +MZ%:6]J;R2G/?-Y>I*6D)>5DA&0FY=XJV%KC@("`8^"A>0X>IEX?'$Q[V1B@( +M*#9&YJZ*CZ='%^GIZ0F9H2&9R3GW8O86..#@(!@X*%Y3!Y<W!^=[7C:VJ&BH +M1N8>DKO_)T?7:2GIR=DA(3E)N>=^%J@8X."@>,C64A_WUP<G3^(VUG8H:-9F +M?G)*KP?W=ZEIZ2D)&2&A:0F)OP96Z!@@X%BX*':NAZFG+Z<O)J@6]JCHUIX" +M<NJGEU=7Z0D):4FAX3FI:??:J&@XV"#@F*A&MNN7M]-#K[H&J-9&EJA&<@J* +ML\<IZ:GI"0D)&>%9B6D7$P9H.!B@X*#(%L;"9S?_+Z_+_C:6MK86=GXBBIL? +M=RDI*6D)B3DA(4EIZ:=NUD@8V"`@>.AVOO,_#S_3ZT)^!@8&ML:FC@+[;V=W +MJ2GIZ>G)(>$YB0D7:T9H^)B@X%B(U@82VV^_XVJJ`E[F)N:FICZ"@W-_QQ?7 +M5U>I:=EA&0G)B=]^U@BXV.`@..C6]LY[+ZOZ>R/BOOX.KCZ>$C/3C]]WUZF7 +M%REYX=F)"0FWPC;H"'@@('B(:.C&@H.K(MMOVS(N<MJN?JYSS\__1Q?7=_<7 +M"5E9B>EI5[.>%FC(F*#8N`B(5N9BJEJK[P^;RN)*2K*.*B\__^>W5ZE7-T<I +M^4EW1W<'FQ[6J"C(>#@(Z.BH1NZR<LHSCZ_;ZX/SVVNS#]]_7V<WQV<GIR?W +M*9>'AP?_R[X&MA:(2`AH:.A6!LZN8OL/OV^SKW\/&UN/ST]O3U\G?[_?IQ\? +MYT?'IY_/\[H.YC865BCH*-8VAJ8.`LHK2T/#K\\O<S./S\_//[__'U]?_[]/ +MK]O;"X/S0_NJBAJR#GZ>7F:&!H:&AN:>CO)ZZ^,SD^]OST\_OQ__G[]//[\3 +ML_.C2^LJ(B("`CIJ.HK*:HIZLI(2DHX^OGY.KFY2FJIKH[-3DZ_O;X_C+V_# +MDZ_32RJZBDJ:.OHK:ZMJ2SOK"XI*:CJB0B*"@K*BRZMJ"JN[NHJZBUNJZ_M# +MV^J*:ZJ+JBJKRRI+8TI;@RJJ:@LKNLKB*NOBFGHC"[N;^W.KHSL+JN+J"POZ +M.@IZ&B):X@KK6BI+.WNK&TL;RXL*>MKZZDHKFUO[6]O#(]M+VRI*:HL*BKIB +MXOIZ2DH:R^H*.NH+ZRN[&SO[RRNZ:HJ*^CO+6RIJ^^M+R]N[:^JKZXOJRKM* +M>BK"BBHKNAHKRPO*Z_NKJ@J*BGHZZ^O+"UM;JTL;(YN[R\NKZ\KJ2NHK^KJZ +M2J)ZBJNBRLLJRZJKB_OKBSLJNQO[R^OKJVKK:INJRRIKNRN*.FOJ2NI*.FHZ +MV@H**TJK*VL[JRJ+"^O+JB-KRRLKBXO*.POKJVNJZCIJ^XL[BXO*JLI*NGHZ +MZBI:JBIJBPMK:BNKZBOJ:VNJ&VN*.\L[>ZMK"VL+ZDMJJ^LJJ^IJ*JLKZ\HJ +MRHJKZNNZ^CIJ:[KJZZIKJTOKJLL[BXN;ZHN+Z^NK"VLJJFJ+Z@OJ*JJZ*ZNK +MJRJKJNLJZROJ*VJJZFJ*ZBH*BBJJ*^NK"_O+2^M+ZROK*ZLK:^OJ*NMK:BJJ +MJBOJ:NJJ*ZJKZZNK*JKJ:FKJZJMK"XN+BVOKJZNJZFKJJBHJJNN+BVLK*ZNK +MJJNKJ^NKJZNKJJJKJZNKJZNKJ^MKZ^NKJJJJJZNK:FHKJBJKJJJJ*BJJJZNK +M*^OK*^MK"TO+BVN+:ZNJJJIJB@H*BFIJ:NHJZNHJJRMKBPL+B^LK*ROK*ZLK +M*ROK*RNKJBHJ*NJ*"FHJJJJJ*JL+:ZMK:RMKZRMKZ^NKJZJJ*JJKJJLKZRLK +MZRLK*ZKJZBHJJBNKJJHJJJNK*RLKZVOK*ZLKZ^OKJZJJJJNKJRKJZNJJJZNK +M*ZNJJZNKJZLK:ZNJBRNKZRLK*ZNKJJHJZNHJ*BHJJBLK*ZNJJ^LKJZNK*^OK +MJZJJJJLKJ^MKZRNKJ^LKJBKJZBKJ:FKJZFIJ*JLKJZJJJRMK:PO+"\L+BVMK +MRVLJJBKJZNKJ:FKJ:FIJZJOK:^LK*ZNK*ZNKJJHJZNKJZNJJ*RLK*^MKBXN+ +MBVOK*ROKZRLKJRHJZFKJJJJJJBHJJJJJJNKJZFIJ*JJJ*RMJ*HN+:XMKBVOK +M*ROKZ^OK*RLK*ZOJ:NKJ*FKJZNIJZBJJ*JJK*VMK:RNKJZHJ*JJK*ROK:XN+ +M:RLKZRNKJJJK*JHJ*BJJJZJJZNHJJJHJ*[O+*VMKRT-+$CHZNHHJ:[HJZPMK +MZTO["Z-OFQIK`H*"2OK:"JKK"_M;.\N[6SMK>TLJJRMJ*LHJRLIJZBIJRNJ* +M2HJKJZIJ^Y.#:UMZXIK:8J)Z"NN+>X.;JQNC2[OCZVJJJZOKB@JK2LJZZFIJ +MJXKKJVHJJRLKZ_NJRFOJ:LNK*COKZFNJJVJ+:XJ+ZJH+ZVIKZVIKBZHJBZHJ +M*FHJ"BL+ZBMKJBNK*XNK*SLKZFLJZJMJRHIJBNJJ*ROK*NHK*^N+:JN[BXMK +M"^N[NWO[R\N+JZLK*JOJNCIZ.CH:>KJZ2FJ*JNNJJLI*:LKJJPL+"\L[^UN# +M@_,S<W/S<[,#8P-[*PH:@E)NSO[^GI[^OLXNDH*:.JO[&T.OD^]/S_]?YZ>G +MAR=?WY_/@QMJLKZ>YD9&MK;V1H;FWN[BFOMS[X\?YZ=?IQ]O+T/+RJ("+NXN +M[E)ZFCMO;P_G9Z>'YX>_SP_KFNX.9@9&MG9VQK:&IFXN(DO#[[\GIR=G9Z<? +M?U-;*_HNCDZ>'G[N+L*+[[_/M[=G=[=W)R<G^^H2CL:V=A8HJ':H=L9>'A*+ +M8Z^?AV?'MS<'!V?_;^.[\NX.7J:FWGZ.PLKC_[^'EP<7MS='3Z>;RN[^AG:6 +MJ*CHEM9V!B9.KFNC[W^'Q[?W=_='1R>_$Z/Z+KXFAL:&!N:^+IIKKR?'Y]<I +M1RE'=Z<OG[(2IN96*"AH:(@6J/;FSA**[Y_GQZG7URFI=[<'/X,KHI[F9C:6 +M]D8&)DXR^D,_I[>IEZD)EZGW!X>*LXYF=E9H2,BXB$BHEK9^HN-O!W>I*8D) +M:6DIEV=?L]I.)D:HJ*@HJ#8&IJXZV^^G!_<I">DI^7<7]Q_?OJ(&J(B(N!A( +M^(C(EB9^2C\'Q^F)"0E)22FIEU^C*HZ&]M8H:"C6UC;>;F*#SQ\GQS=WU^G) +MMU=)#X=_2X+V7NB(^&CX&.@(5A82"L,?URD7R4F)Z8FI)Z>38J9F1B@H5E:H +MQAY^`B/O;]]GIQ^GI_^G-RGGQTD/_R<+CA8FB`AXB(AX-H:^CE]G9W>IZ0<W +MM]_[,QM>/HY>9CX2[D([[[OCOP,J2SN2KB(N;O(**Z]GJ4FIZ5D')T<J9FB6 +MF'A8^(CX!NYC&]=I%^DIJ=_/,PH^'DYFWOY"NBI#3[\S?Z_JRAJN?@[.SN[B +M2Z-3IY<)>>D)H9^;O[Z(F&B@6-C(-BC"_W=?*4DWAR<?$OZ^_J;F.LM;C^?G +M3_]OF\(2+EXFWHX^;JK;6Q/?']_GMPEY=P<9?P;B#@@@:+CX2"A:SCK_Z>=3 +M5^<*+@NNYIX2&RO39S=GY_?/2^HN)@:&QJ8>KHN[@V]_#\^_SS]OGXEYGQ]Y +MKY;^$@@@Z&AH:)9[RTI;*8=JIR=K'J(ZDA(:GQ^OSP?_6HJJCF8>\J[.VE/S +MFR_?+\NO3[.C[V?)N?]'22JH!CXXH&@H5BAFLP\CHU<'JUMOZB:.LB):.G^W +MIV\')]INXNX&9BY:`OK3/U-SGY^S(^_3X[_I^<=O::?VZ&96V$@H1D9&HD^G +MZ\^W;QH"JRX>SLHOL\^7ES_O;_I^IB:FODY"8W/;;Z?_[X\/[^/[DY>9Z6K7 +MJ2;(=G[X>"AF_O9.HV=C`J>GF_[R"JY.<B<'$S_W9Z)"RF[FAO[B6O*[G__3 +M#R??TP,O#R^'>?D#3Q?Z",C&"#AH]B[.;F)?YQJKDW,.AC[2R@)C=]=?OP>_ +M\GYN[AZFCBM[>LL_GY-S3T^OP],GB:$I.S<'QGAHMKBXZ-ZB/NX[QW\Z.R\# +M)K:FTH**G\?'9Q_OFZON/BXRKJY*>UN#4[^_KY-OCQ,OEQEY3_,W"XAX5JC( +M"!8RVNY2CT<OZNL3J^:V'LO[B\\WM^_[V_LRG@[:BO+".],#V^\?_\-C+Z]S +M)[FAU[.'_X8X"*AH:&AF@A(^,I]_>V*JD\)FYBOO[[\?9Z>C\D**TO[NBKNK +MJP._?V_O/T_#V[,/QTGYAWL_RY:XZ-:HJ)8^FEKN6L\/^P)Z*]+>CO//4^__ +MWX]KTL+Z4KZNJSOK:Y,_O^_O3[_O+X_G:9GIPT/37LBXZ%;6J$;R*X)NRS_O +MNJZ:6CY>^J^OK^__'V_*0JJK0BXBJVLK:Y._3V_/_S^/K[\7.;E?JD.:5OC( +MJ!86EM[*"\*"D_^3HF)*@DZ2>Z-#KZ^3KUOB8BMKFB)J>^,;&S./;Y-S;[^/ +MCS<YF3?KFVL&2$CH%G;61BY+RK*+S[^KTD):<BXB`_]/K],/$XJ2\KKJ8L(K +MDW-;6R_/[T/S+V^O[P<)>9=+J\O>B+B(%K9VMOZKRZ)Z\S\#(A+:J]I2&F_? +M;UM#[\/ZTL(*R@(BFR_3FV//?V\S[S__S]^I21?;8CKN5@B(5D9&-H9"&^MZ +M"^\O2Z(B(H*:*N/3CV_30^,[:IIZ&AK*:[NC0_-S+T]/CV_/ST^WB2EO>HKZ +M!NB(Z';&MO:F.LMJ*H/O[\.K`JY:^UN+X^^_KUM+.]M[2B)*NXOJJ]OS+U/S +MTP]/[Q._]^FWXQJK^N86**CV9D9V9C(KNTN;D_^/:T(BRR/+&OHC;\/K*IOS +MKULKN[,S([M[<^\38Z.#L\,;BWNOOZ\*8JMJD@Y^)M[.WF8>[G*"XL+:*\L[ +MHX-S[R\3,^-[>SN+ZZN*ZJJ*RFO[&[.30[.OK[.#VTO[\P\3ZR//\ZOZ<CX^ +MON9&YA[>?O[^+MJ*"YN#[T\/;V^3`\-[JJJK:NHK*XM[VX/3TQ/34W/#V[O+ +MRR/O<VJ;;Z/Z&A(^#HXFAJ9^GKY./FY:JBO+PV^/#\\3@Y/#"^N+*HHK"VN[ +M(X,S4U/S\W/S<Y.#2RHK^^/+\@+CF[*NK@XN0DZF3O)R$M(N\@J+:VN[H_/S +MXTO+FZ.;R\M+>Z-CHZ-#,[-SDT.#LS.#>[MK*HO[^ZJ*B\NZXL*N[JX.GO[. +MS@XN+M):*LM[6P,S<T-CH]O;>TN+B\O[VR/C`S/S\[,#@X/CXQN+*ZLKNZ.[ +MJYOCZYKBK@YNSMY>GKYNCHZNPOJKRQO#<_.3$T-;6UL[N_N[N]LC6R-C@T.3 +M<T/#PV,;RZOJZHM;F^O[XPO*>O*.C@X>7IY^/H[N4H)*JXO[6X-#,S-CV]NC +M&_N;F[M;8UMCLW/3KR]3\\/C&PMJ^MIZJLLJ*CL[JLI:4FYNSO[^/DYNTG)" +MVHIK>Z/C(P/S@_N[^TL[&_N[HV-C`\-CPY.30T-#0P,CNRNKZ_L;RRN[2VIZ +MLFX.SOY>WIX^CBXN$F*ZJDM[6[.OKS,#8R,CXZ,;6V/C@[,#8S,3LV-C6QM; +M.ZHJ*JH+RZJJNTLJ.H*N;FZ^'I[^3FZN$D)ZZBJ*ZSL;@P.#@X/#L\-C8T,S +M\W-S\W/SP^.C6YM[.PNKJJIK2XMK"^L*>H*N;@Z^?GX^O@[N[G+:2NKKRSO; +M@P.#@\-#LS-#0[/S<Y.3,S/S\S/CVYM+RRLJJZLJJBLJBNJ*^MIB,M*NCDZ^ +MODX.;B[2PEJZ:BL+FV,SD],3TU-3$].O+R\O4_-#0X-;&WN[RXNJBLJZ>GIZ +M6EH:VEHB8L)RKBYNCNXNKA)R0B)Z"BL[VX.S<].O+^_O[R^O4Q,3,V,CX]O[ +M2^LKJRI*.CK:(F+B(@*R,K("`H(:NOJR@MJ"VKHJ*ZKKN_N+.]L[2YM;F^.S +M6UMC6^.C^]N;FTN["PL+"VLJJ^K*.OI:>IJ:HIJ:VDK:.DJ*NDH*^FJ*BHKJ +MJZOK:RO+RTL[.SN;&UM;VUM;6WL[RXNKJRKJ*HIJBHJ*NIJZ2KJZ.KJZNKI* +M"NJJJZMKBPOK*^MKBXMK*^L+2PL+B^OKZ^N+2SM+R\MKJRHJZDI*2KK*2@J* +MZJNK*JLKJJNJ*BKK"PL+BXN+:ZNJ*FHKZVJJJFKJJ^LKZVLKJBL+"VOKB[O+ +MZZNKZZMJBDI*"NJ*ZNLK"VLKZRLKJJNKZBHKJ^KJZBJJJVHJ*RNK*XLKJXLK +M*ZMK:^H+B^L+:\OKJBHZ:FK*JNIJZXOKZ^OK:ZN*ZBJ*BBIJZBJJJZKK*XO+ +M"XOK*ZOK:XN+:^MK*ZMJZBJ*"@IJBFKJZJNKJ^OKJPN+:\OK*ZMK"RLJJVNK +MZFH*JXOJJNNJJZKJ*BOKJRLJJBLJJRLKJRLKZNHK*NL+:POKJJN+*ZNKZJNK +MJRLJBHJKZJHK:ZN*JRLJJBMK*ZLKBRHJ*NHKZBKKJJLJ*BLJZRI*RJHJZFMK +M*XM+"PM+"[O+ZRNKZJJKZRHJZHHJ*FH*:JH**BMJ:NIJZBHKZZJ+Z^OKB\MK +MBZMJBTL+*BO+ZVLKJNKJJFJJJZH*BJJJ:NH*BBLK:NJK*^LKZPN+ZZNK:ZJK +M*PL+ZJJKBHJKJNL["XLKJPNK:DHJB^KJ*NOJRBLKBNIJBJM+BZNJBXLJ*BN[ +MZ[KJB^N*.JLKJZJKZVJJZVLKZBI["ZKK:[NKJVKKJHL+*BL*ZFJ*ZFHJ:JL+ +M*RJK:RNK:P.?8R:>NHLZFFLJJQNCFXNK*^M+"VM[FZL*"@JJNRM*JHOKZZJK +MZFM+BAH*JRLK:ZL*VKHJBNHK:ZKK^VOJ:DO;ZXNK*JNKBVHJZLKJZNM+J^KK +M"[L+ZLKK>^NJN\LKJHOJ6DI*NJH*2HK+2^IJ*PN[JXM+"FOKZNO+ZDIJZLHK +MFSO+2FI+"\LJJFMJ"GIJZJJ[*VIJ*VMK*\J*ZTOK*@OK2PN*RNN;JWH:NFI[ +M.PHZBJKK^\NK*NM["^I*2JM+JDIJZRIJBXN+:FN[^ZH:RHJC6XHJZFLJ"JKJ +M2XM*"BJJ2BJ+*JMJ*B/;:WI*:XM[*KJ*:@JJ.TMJ*NN+RVL[*NHKNPO+^ZKB +M\OJ+.ZHZ(CH;XRO*"SN*.R\*[G+ZJKN+>GJ+8]M+:TNKZFOK"\N+BRJ+2YO; +M*^J*>BJZ8DKK.XNJJLJJ*JK;R^NKJ^K:6FO;JX("FNK[F^O+BRN;>PN+.PMK +M:ULS2XIBPJ+:NEIK,P-+&FHKZ[OZFAIJ2^IZ2LO#@_MJNNN+*CO+:JJ+*IJZ +M*HJKJCHZJ]N;6]L+:VJ*R^NZ*LHZ2HO[:ZLJJPI*:DH+:VJK"DHJ"[N[ZQL[ +M:RIJ"GJ*2EJ*Z[NK^HO;6YN[>VLK*XKK*FHJ2LIJRFKKJJJJB^LJJRJ[*HK* +M:HN[^RJZ.FH["XO[2XMJ:LI*"KJ*JROK*NHK"SL;^XOJJHN+^AJJJFLCX_NK +MJ^NK*DI*NCI*^CJ*:CJ:>KHKVS,SHXO*&IH*:]NC6QL[*^KJJXN+JFK*FAJ* +MJVLK:@J*:BHJJNK**JNK*ZLKR_O;>WL["VNKZCH*"XLKBII:6OK*"BO+.[MK +MJ^JJ*RNK*VMK:XMK:^NJJBHJZTL;HUN;RZO*&IKZ"BJK*VJ*2DJJ2QLCHQL+ +MBMJ"@F)ZBNKJBOIZ(H(B^NKJ2[L+V^,#@^,#8R-C8P/C(_OJ>@)R,L*B6KI+ +M[V<7*>D7GS)VR'AXR-8^2T_?GX_#FQL#TR^O,QOJ>OIJB]OCHTNK"KH*JJLJ +MBCK:&FJ[\X]/3P\S"YKRKJZ20L*B>Z>IR?FY*:\&..!@(+BV"V?W1]\;DLXN +M.@,/3^^CRN*Z@U\WES>G(^Z&ML:FLILOC^_C*PHZNFJJ*HI*2BH[XT,C^^NB +MDBX.#OI?Z?D9>>F3-GA@@"#(IL\7J7>?VB8&IA*#G]\/VR(NTBJ/QZGIJ4<O +MLN;VED9>LGO3[Z^CRC+NCNY"2CNS[^]3PSLJNGKZ:LM[*N+R:X=I^1EYJ>NH +MH,#`((@N!^GI=R^^-G9FP@^'!Z?3FF[N2H^W*8EIE__BAJCH*/9^*N\?7\\; +M`OXF7H[Z`[^?/^];2L)"HJO#[X\O8PJNKG,7R7EY:7-VV`!`8$B>)^EI%S^N +MMA9&+N]'=T<?>W)N,GNG=ZDI%R=;+@865I;&_KHS/Q_/._*>9N:^6L.?YR?_ +M,^KBXCK[+S\_CUO"IK8F<RGY65F)XZ@@L+#@"+)W2<FI3W[6J$8R_W<7M_\J +M#CX2(V?7*2GW?\K>-JBH=F9NR\]?W^^*OH:VALZ['[=WMY^;<DZ.FD,?9R=/ +MB\Z&=C;"-SE9H;D?-MC`L(!(/@<)R5?_;I:H1C)_URF7ITO.IK[*/S>IJ1?G +M"QXVJ"@6ABXC'^<G#^J^9L9F#LM_1_?'_QO"CBX:6\^G'Z^*3H8V)N.I^5D9 +M:;LHH`#`H"C:-XGIQV/>=O;>Z^>7EX>OHKY.8O-GE]=WQS^+CF8VEO;&'B+S +M?]]/V]*F!H;^*C_'=[>G`R*.#O(JDS__+^LNIIX[]\EYF6GCUE@`P""(4D>) +M:7>/3C9V9D*/!\<G[VKR`@M/Q]?7]^>S`AZ&MD9FWJ[*VU/O\^LROEX>CAK# +M_R<G?U.+FJ(*VU-O[T,JKHZJYVDY.8G_ACA@`&`X1H/WJ7?G&XX>3@);S\\3 +MVPK:JG,?QY<7]\<?FU(F=E;6]N:RP_^G'Y,Z#J9FWJZJKW]?WW\/4T,C&[LK +M2MH"ND\7B4E)UZ/&2"!@H#BH#K/_7Z</,_.O+^_32R)2[O*+#X?WUQ<W9Q\O +MBW(>1M:HUC8>^G._/R]+HM(N,HJC4V]O4_,#8S.3DY/#>ZO+CP<7J5<'.R:H +MN'@X"*B&3I(:"UL3?^<'AR=OZR(2DCHCSZ>'!X?GGR\;^N[>9@8&YO[2.LO[ +MN^LJ2KK**LL;HP,STR]OCV^O<^/[ZVJZ^NJ;,U.O$YM*$AYF!H9F)IY.CJX" +M>JLCT^^/;R_3TZ\O#S__/\\OPSL*(C)R,@+B6AIZFMKBPC)R<C)"@B)Z*@M; +M,R^/#P_OKY-#HSO+*RJ*RKHZ.IH:&B*"6J(BFCH**BOK*ZOJ"KKZ>IKZ2LKJ +M*XO+NWL;6Z-;VQL;V]O;6]O["RMJNGI:(J*B(J(:^KIJ*TN;6Z-;F_M+"PMK +M:XL+R\N+ZZIJ"DJZZBH*B@KZFAK:FKJ*JFO+RPMK*ZJJJBN+"PN+BVLK*RLK +MJZLKZZNK*ZNJJJNJJBIJBNJJJRMKR[O[^SL[N\MKJ^J*BNHK*RNJJBKJBHH* +M"FH*2BIJ2LK*:NO+N[O+B^NJZNKJJROK:VOKJRN+"\O+RXNK:@K*"@J*B@J* +MZBJK*VMK:XMKZ^OK:^LKJZJJJRMK"[M[F_M+BRNJ:HK*NOIZ>LK*^LJ*BJMK +MB\O+:ZHJ*BHJZNKJ:NHJJ^N+NWN;FWL["VLKZHH*BHJ*BHJ*BFKJ*JJKJZLK +MZ^OKJZLKZVN+:XMKBXO+BRNKZ^LKJZNJ*NJ*>AK*RKH*ZJHKZVMK:RNKJZJJ +M*BJJZVN+"\O+RXL+BRNKJBJJJBJJ*NIJ"HIJZNJJJRMK:VMK"XMK:XO+2TO+ +MR\L+B^LKJRIJ"DKZFIIZ>KJJJ^JJ*FIJZNHJJBOK:XN+R[L[^SL[.[L+ZZLJ +MZFIJBLJ*:FIJZJJKJVMK:^OK*RNKZXL+"PN+:^OKJZJJJJNK*BKJB@K*2LK* +M"NHK:VOKZ^KJZRLKBVMK*ZNK*^LK*RLKJBHJ*BKJZNKJ:FHJJBOK:XN+BPO+ +MR\N+:^OK:XN+BPO+2TL+:RNK*NJ*"@H*"LH*:FH*RDI*2LH*:NJJJZHKRXNK +M*ZNJJRLKZVN+BVL+"\M+RXLKJBKJ:NJJJZNKZZNJ*FIJZBHJJJJK:XL+2[O+ +MBXN+ZZLJZBKJ*BJJJRIJ"@H*B@H*BFHJJRMKB\O+RPNJ*FNKJ^NKJJLKJRLK +M*RNKJBKJ:HJ*ZBHJ*NHJJ^LKJZJJJVN+RTO+"\O+2[N[NTL+"VLK*ZKJ:FJ* +MRDI*2DK*"@H*BFKJZBHJ*JJK*RNKZ[M+:VNKZBHJ*JJKJZJK*VL+BVMK:VOK +M*RLK*ZNK*RNK*NKJ:FIJZBJK*RLK*ROKZRNKJZNK*^N+"XOKZ^LKJNJ*BFHJ +MJJHJZBHK*VMKZ^OK:HHJZJHKJZJKJNHJJBKJZFH*BFHJ*XL+"PN+"PN+BPL+ +M"VOK*ZNKJBKJ:NKJ*FJ*ZJJKZVMKZ^OKZVOKZVLKJJJK*FH*RFIJBHH*"@H* +MBBJ+ZRO+"\L[N[M+RXMKZRNKJBKJ:FIJZJLK*^OK*ZLJ:FIJBFHJ*JHJ*BHK +M:VN+:XN+BVMK:RNJ*BHJJROKZ^OK*^MKZRLKJNIJ:@H*:FIJ:KJ*JBHJ*ZLK +M:VMK"\O+"PO+"VOKZVMK:RNKJBKJ*NKJ:HJ*:NJJJZNKJJJK*^OKJZLK*^LK +MJZHJZFKJZNKJJBMK:VMK:^NKJBHJ*NIJ*BHKR^NK:RNJJBMK:VN+B^NKJBHJ +M:@H*BFJ*ZNJJJRLK:TM+JRLKZVLK:VNJZBN+FYMJ>CJZJBIJ2AK*ZRLK"]O# +M^RK+&QMK2FKZFIKZ>EKZ2DHZ"BOKNWM[6R.C6YL[RTN[*\H*NVM:ZLO*JJNK +M.OHJ2HJ[.EJKZBM*2@OK*VK+^ZJJ:ZOJRNM[*@I+JRNKVCO+.BN;H\K[0ZIJ +MRZ,K"NHZ"PK:2VJ:JBL*Z@M*2SO*ZRIKJ^O+B[LKNVOJ*[JJ6EIJFMK:2J): +M^MJZ>HHK:_OKHYO;KZ.SK_L#`\.S"_M+ZZKJ*RH*(LKZPKH:(FKJ"JJ+:NM+ +MZYM+"\OJBIKB@G)RKJY2DK(">LH*BPO[VP/34U.O$_,S,\.#HYMCR\N;ZNMK +MRHMJ:FHKRCK*NJ/J:G,KZX.J&THZJQ)2+LY^'OX>?L[2,O(JNR/3CS^_?Q^? +M_T^_+P/;J_H"TA(NDD("(KHJ2KO[6\-C4S/#PR/CLY,+8V_*LYLJ>RZ*KGYN +M7G[F)MXF'OXN[L+KNQ/O?Q^?YU]?G\]/$P-[J_IB`JXN$L(BHJKJZQN[XP,C +MXZ.C`]-#.R\OZN_+.SNN>\[.[J9^9J:FYA[^;FZBJLNS4S\_'^=?IQ__OY/# +M.PK:@O+NKM*2PEHKRWOC(\/#\].O+T^O`]^K,_.BTTY*$B8NAEZ&!J:&IEX. +MCD+K2U-3?Q__9U\GWS__\[-[2MJR,BZN\G*BVNN+2P-;<]./OS^G+U]/H]^K +M,^INBN8>9D8&=L:V!F:F3L[Z:EOO3R>GAX?G9Z??3R\3NZJ:`A(N+JX2,AK* +M:MNC\V_OGZ?/IX<OWR]CLVX*/F8F-K86EC;VMF:>?D)J>R]O9V?G1P>'YZ>? +M[S.;BN("4NZNTK*"&BNK>P.#+\^_9_]_-U.G3]OOCOK.AN;V]JC6UA:6-EZF +MTJO;#_\'!\<W1T=G9Q^/TWOJ8G(NCH[NKI(:6BK;(X]/GP>'7_=GOV=CKZ*. +M\D9&EM8HZ"@H5A9F'KYK(X\G!_=WEQ>7M\<G3Z]+^K+.3AZ>_OY2\IIK&],/ +MIR>'EV>'EW^GO[O[?DYF%E8H:,AH:"@6-DYNZC^G1W>IJ:FIUS?GIR]K^NZ^ +MIF8FYB:^KF(JPR]/7\>WM^DWQ^F?Y_\JB^8FEN@(R,AX",AH%C8NVC-G=ZGI +M"8EI*:DWW^][,GZFAC;VQF;FCKI+,W\G9S?75RD)]U<ITY^[CB96J$BXF/CX +MF(B(%F9R<Z>7Z4E)23D)J9?G0QI.AG:HJ*BH]B:^@@,?Y[?7J:DIB6D):>?I +MW_*C)O8(B/A8&*`X&$@61@ZCQS>).?F9.;D)EY]3\D;VJ&B(:"B6!KYK<Z?W +MJ2GIB>FIJ:DIU]]?ATZ^GA:(N`B8>)BX:`BV;CI;QZG7";E)"6G7I]-27K8H +MZ.@HJ$:F[LLO)_?7J6DI5Q<WAV=WUP^S%TNF`MX6R.A(.'CX*`CH9FH:,U>I +MJ8FY":G79U.RIL;6Z"C6%D8^6ML_AQ>IURGI=T?'IZ?WUZ=31S^^WCYV2$A( +MN!B8B*@HQCN/OW>)B6D)"5=GOSO^ME:HZ.C6!GX2`U\']]<IJ=?WQR>/$T]W +MJ;_OZ6?>4N(VN,A(^!A8B%8H-J/?_W<)26EI:==_.K*F5F@HUJ@VODL#/[=7 +MUW>I5P>?_^\+*M]IJ0]'"5^^[JZH>!AX>""@"+;VII_75RFY><FI]P>[9G:6 +M:$AH]F;>*Z>W]]?IZ7<'AQ^;*DHBRS>Y5Z=)2:\.$F:X6""@6&"@*.;F:Q<) +M2;GY><D'SZ]>B(AH2`BHIDJ3_Q>)Z:DIJ<=/8PM:/CYZAWGICYD9IX**/KB8 +M@."@8&#(?N8[%[EYF3DY.6=+.B8(2,A(Z%9F^V<GE\G)*1=W!T]Z4F)N'F[/ +M.5FW:2')6]Y>B!@`0.`@8*`&FJ^W25DAF<FY*<->-NA(>'AHQB:RY]>I*0D) +M*<<_OUN./NYNTH,)X0DI67DGGL8(>&`PP"`@(.@NCS=I>2$A28GI)\Z6:(A( +M>,C&+J)/%^EIZ>GIEW_#VX+>'D[NNK?9.5<YF:DK'JC(V`#`X"`@.#:BWQ>) +MF:%Y26GW$PX6:(BXN.AF[ENG]RF):>DI]Z>/N_+N[BXN^]?YJ?<)B2=R9JB( +MF&!@6%C8",::/T>I.9FY:2EWO_+&]G;H:):F\NKS)Q>I%]>IUP<_DS,++CZN +MZB<7)U\7EX^Z#@;V:)B8N/CXB'8>.N/?J6FI5RD7Y[/B$HZ&]H9^CI*Z+\?W +M-Y>IEP=_KQ,[0FXNLDJ/G]./7S\;FLZF!E9H:.AH*!;&_IH;3X='1S='YQ^O +MBXH"3LY20FH;`W_G)^?GG_^_TR-[*QH:(H*"ZQ-3PQ,3H^IROAXFQC;VMD8& +M9CZ2^JN#[\\/C\__OS-;X]L+N^NCKW,OSS]/[Q.O;]L[&PM*&B)BBIJZNR,+ +MJPNJ2D+N#FZ^IJ8>?IX>OI*BXB+K>Z.S0X\_CR^OKV_/[R\/[X,S+_-;"^N[ +M"POJJRHJ^AIZ>AH:>GIJBDJ:.J*"PD(R\E+N[NX.;FYNDD(ZJP/3C^\/?W^/ +M_T]O[_,36W-;6\L+JHK*"BH*R@JJ:DJ"LK)",L+:.HHK:FJK:\OK*CKB$E)2 +MKHYN$N)Z*LL#T],O[\\/#].ODW/CH]N["RIK*^MJ*VHJZDI*^IH:8C)"@B)B +M>KJKBPM+VYM+JRH*&H("PD("`OJZ:ZL;VX-#(S-;(WO[(WN[:[L[N\M[6YO[ +MB^L+*DK:FEJ"@N+:&DHZ*RO[&WL[Z[MKBAHZFMJBFDI*^HHK^\O+BWN;RVOK +M"ZJ+BTN[2XM[>YL[>PO+Z^JJJFJ:6IKZ2FIJJZJJ*\O+BZLJBFJZ&CIZ"FKJ +MJNN+N[LC^WN[N[N+:ZHK:NH*BFH*ZBK+BXNJRXNJJZKJJLI*2HJJ*XN+BVO+ +M:VMJJSJJBLHZ"FJKJFN+R\L+^[L[^\MK:ZLK:@K*BLIJ*JHJ*HMKBRLJJDH* +MRHK*BBJKBPO+^TM+:VLKZXMJRBIJ.KK*ZNJKJVOK:VN+"PMK*ZKJZJJK*BHK +M:^LK"\M+2PLKZ@J*B@K*BFKJJZNK:VMK*RNK*ZIJ"@KJ:JKJ*JLK:PL+B^LK +M*ROK*ZLJRJI+BPL+:^NJZHK*NDK*BFJJJ^N+"TM+R\O+RPOK*ZKJBLI*2@IJ +MZNIJ:FJJ*^MKBVMKZVN+:^OK*RNKJJJKJJJJJJHJ*FJ*ZBJJJZJK:[N;2TL[ +M"^OKJZIJBHH*NCI*BFIJZJLKZXL+B^NK*FIJ:BJK*RMK"[N[N[L+ZZHJ*BKJ +MJJJJJBJJJNIJJNMK*ZLJ*NIJZJJKJZNK*ROKZ^MK*VHK:ZNJ*NKJ*JJJJJHK +MZXN+BXMKJZJJJFIJ"HKJJVM+2\L+:RNKJ^H*RLJ*:NHJ*JLKJZLKJJMK:RLK +M*^MKBVN+"XMKZ^LKJBJ*"HJ*BHJK:^IJZFHJJVN+BPN+ZZNKJZJJ*NKJ*NHJ +MJBHJ*BHK:PN+BXMK:^LKZVLKJJHJ:HJ*ZJMKBPL+BZOJ:HIJZFKJJ^MKB\L+ +M:RNKJBIJ:FKJJNK*JFLK:RLKZZNK*ZLKJZNK*RNJJBJJJJJJJZNK*ROK:ZNJ +M*BHJ*JHJJJLJ*JJK*RNKJJJKJBJJJBOKZ^OK:XN+B\O+BROKJRNKJBKJ:HJ* +MZJH*RFKJJJJKJBHJZNHJ*JJKJFJJ*^O[.]L;^_L+*RIK*ZHKZVO+`],B+MIK +M@HY2[EJ:[S]+"TN*.HHC2RMKFR.JBOL["LJ[^\IKJNNJ:JL+:DJ+2VH*:VN* +M"BH**II*B^O*Z[NKZPOKNFHJJOLJ:_LKJ\LK.BIZ:ZOKJ\LK:\LKJ^IKJPMK +MBRLZNN)J:IJ*ZB+*^QJ+:R-SHR/;KZJ[^PL+BJMZ^G(*^EKB^NK:BDHK:FJ# +M&VL[.VMKRSN+*JO+JRI+.\N[6R/;FZ.C2PN[:^K*^MJR$A+N#NYN3NY2<@*: +M"LO[VS-ST^\/+R^/KQ,OL\.SF[O[ZOHJ(X]+X^>3XR\3ZD)B;C[&9@:6%D;& +M-N:^DN)+#Y_GQW>7]_?W9Q_/@[KN3EYF!F9F9IZNFNM3SW_GIZ>GG\^OT]]? +MRL]G*ML3^\(.CC[&%F;V*)8V]K8F3I(2H[\/)_>7EU?7E[=GYR\KNE*FYH9& +MQ@8F?LX":R,O_Z?G)R>G?T\3`TN3CWIC/XJJVZOZ4C)2IH:FQI:VMK:VYD[. +M+FO#\W]GQS>75W>W]X<_;]MZ4DY^YH8F)B8^+G+Z2P/3;_^?_S]/K[.#BXK: +M6N,++F\S6F_;TXOJXV(.S@[&A@9&1K;>IM[2"NHC/]_GA[>W1\>')S]/P[MZ +M0BZ^/IY^?L[N,GJ*NYLS$Y.O4_/SX[O[ZNH*NO/;PD_S:D^;CSOK,T+NCCX& +MYH9FAL9^)GY2PIK+$X_?)\?'!\?GIZ?_K^/KZB*N+@X.;M(R8GI**JO+R^OK +MJ^OKBZK+>^M+B^N[LPM[W[-3#R\/RS,+$BZ.GH9F!@:VAB9F_JZ"FGLO3_^G +M!X='1\<')Z=/T^,+`A*.WGY>'IZ^KC*B:DO[`Z_O[V\OD].;:^JB(EHJLIKO +MZUOS(Y,J`\MBHB*N_KX>/EX>/AZ.[I(":J,3CQ\GIP=G)Z?_OW.#.SH"@I+N +M;@YR,F(:&OKJ2LI+JTO;@S-;(\/[2_MZ^FMJ.O/;HV]##_L#,QJ:PJ[>WJ8F +M9@:F9I[.+J)JXQ//GV?G)P?G9R??_U,#2_H"\BX.#HXN+C+BHCH*ZPO+^TM[ +M2\L+V[N+^^HK.\,CRV]36U.S,XOKBX*2KLXFIB;F)J;.#JZ:BJK[,U,/?R>G +M7R<GWS^/0[NJVO+N[HZ.4K+:HDHJ:NNKRVNK&WL;XYN;8\L**\H*6P,+PS\C +MPZ^C&VJKFE).OAX&)N:&II[.#G(*.\/OG]^G9P>'9P<G?[]3VPJB[G[>7AZF +M'KYN<N+JNR/#DZ^3DP.C<X-KNYN[*RJK:P,#:^_/2P-O@R**2VY^OAX&MF:& +M!F:>KM)ZX^_/GP='A\<W1Z>GI^^;Z\HN/CZ>IB;>OLYN,LH[NWL#D\/C$Z^S +M8UO;XQL*>@O+:OJ+@X-;FW-3&ZN*ZEHNSKX^GMX>_L[N4N)*BQO#KV_/3\_/ +M#V\OKQ-S\P.CNVLJ2II:XK*2TE+2$I+R@MIZ2NIKNYNC`[,S,\.#@P.;:^NJ +M*JJJJHJZ.OHZNCHZ.CIZ^CKZNHKJJBMKZ\O+"TO+RXLK*^N+"VL+"VLJBLI* +M"@H*R@J**BOK:PO+2[N[NSO[^[L+:RNK*ZLK*^LKBFHJ"DH*"FIJBHJ*"LJ* +M:FJ*"FKJJBOKBXL+RPO+"PLK*JJJ*ROK:^LKZVMKB^LJB@K*2DI*:JMKBXO+ +MRTN[2TN[NPN+:ZLJZBKJBHJ*"@HJRCI*NCK*ZBMKB\M+R\O+B^LKZRNKZVN+ +M:ZNJJRLKJRNKJZJJ*NIJBFJ*"@K*BFHJ*JJKZVMK:XL+R\L+:^LK*^LKZRNK +MJZIJBFIJ*NIJ:LKJ:ZNK*^MK:VMK:VMKZ^MKZRNJ*HJ*BNHJ*JJKZVOKZ^LK +M*ZKJ*JKJZNHJJJLKZRNKJRMK:^NK*RLK*RLKZVMKZVOK*RIJ:FKJ:FIJ*JKK +MRVNK:^OKZRLK*ZHJ*BKJZBJJJBJJJJHJ*JJKJZHJ*NIJBHIJ*JOKBPO+R\M+ +M2TL+BVN+:RNJZNIJ:FIJZFIJBNJJJJLKZVOK*ZLJZFIJ:FK**FNKZVMK"XL+ +M2\L+BVLKJZHJZHJ*:@I*2@J**JHKZROK:VMKBPL+"VOK*RLKZ^OK*ZNKJBIJ +M:NHJJBKJJJJJZFJ*:BJJ*^OKBXN+:VOK:\NKZJLJ*BKJZFKJ*NHJJJNJJ^OK +M:^OK:XN+:^OKJZNJJJNKJZHJ*FKJZBJJJZJJJBOKZ^LKJZLK:VMKZ^OKZ^OK +M*ZNKJRKJZBHJZBJJJZLJ"HJJ:NJJ*VN+"PO+"PN+*ZLJ*JHJ:HJ*:NHJJBOK +MZ^LKJJJKJZNJ*BKJ*JKK"\L+"^OK*RNKJJJKJRNKJBHJ*FKJZFHJJJNKJZNK +MJRHJ*BL+JJIKBXL+:^OKZRNJJJJJ*JJKJBHJ*BHJ*JJJ*NHJJZLKZVMKBXMK +M:XMKB^LKJZJJJZLKJZHJJJNK*FH*R@H*"HKJ*JJKZVMKZ^MK"TL["RHKBROK +M:^NK*JLKJZKJZNIJRDJ**JKJ:NKJ*BJJJJNK*VN+BXMKBTM[(W,#NMH*.HI* +MNCH:6B):^HJK"[L+2UOC+R\C(\-[*@K:KBXNKK+BHCIKX[-3T_,S6^LB(MHB +MLI(BFDIZ>HJ[0[/3D_-3TU-C"RK**OK2DGIK*@IK2QLKVGKZZAH"6DI;&PNC +M6UN*^LI**IIZ&KK+ZDI*JTL*:NI+,\,CV[-#*GHB^OJB&DK[X_,#*XN+N@+" +MXGJKZCHKN^NK.UO+"\NZ>BHKVKICPWO[6PL*"OKZJBI*RP-[:JH*&IHBPII+ +M.^K[KW.+.JJKRGKB.JJJ:TO;FZL**LO*&NH+:XHJ2]NC.^NJ:ZM:HFIJRJJ; +M>VOKBLKJZLIJFSOZ.BIK*JJ[FYN[:LIJNK*RBB.#&R.OK\NR[I)"<@*J\V\O +M@TO+.^IRPBH*^FIKBSM[NCJ[2WHZ&WL**WL;NXIBHFLKVFHC`WNK^AJ*.O(B +M^P,;6\/C2TIBHHIJ&@K;@_NK"_NKFD+BN@J*"\/S&ZM*RJJZ0MK+RXKKHX.C +MNXNK:OJBNFHZRLL;.^NKBWMKHAJ[H^NZ"BKJ.II*RQM[V^.;:EHZ:CK:.NMK +MB\N[NXN[2VNKBHH*RCJ:BJJ*ZOMCF^LKJJMKZOHK&VKB"OL+NBJ;FTLJ.FHK +M2@+B:WNKNFM#6[HZFZ.JJPL+:ZK*2FOKRJH[.ZL*RCH*.F(ZR[NKZ_L[ZPK* +MZ@L+*JN[2RHJ:XN+:ZMK:PJZBFL+JXM;VZKZ^CH:VGJZZYN[B_L;RZK*6DI+ +M:XI+@UMK:KJZ.MH:Z^/[JKM;.RHZ^NHK"JI[^XN+"VOKZ[J::JJ*2NJJZBHJ +MJ^I:PJ*:>OKJ>UO[RXOKZRKJB_L;6T/S([LK"PMZKA)*:MHZ._.?=W=_ST\* +M9G;VEG:&?MHS#X\/OUNB@G*.SO)J0_^GAP=/>TMZGN8^CNZ:"X/OSQ-S3Q,* +MJ]NK8N(:HDHZKJ[ZK^FAR:-_]W[8V(A(2);N?]?7AT?WHP9&)D96!KJ?M_<7 +M*2GGZG+N)K9F$F/?EXE7WZ_RELA("(BV+N-GEW>'YQ\*;I(";N[+\[-S`\NB +MSO\!`4Y:H1>@`#8HX/@VNP>W)X=)1\;&0J:X"`[+4W\W";GIWP]/TG:6)M[> +MBE\W%REI=ZL&%HB8F(A&3AL'J2F7Y[\3>D[NXO)R>S_/$P_C<GYNJ8$IEBDA +MCF"(JAB`Z&ZN3N]'%RDOZY\O!H@FXN9^4S?W-U<7MS\JLNX>1F;2.IOGZ2E? +MC]/^:$AHB`CV$L-/AQ?7-R?_/T.";@)*8OH[H^,[BA)2_WDYD@_9Y[C(XQ:` +M.#[&"%X'GS_'%Q=G3PIB(N8&OF(RFE^''^<WMP]C&^(.?DZ"\]/RNY\Z9CXJ +MYJC^8IX>6[^[<V>'SX_GO[O[XTM:&GJ"HA(.4NX.LVGWVO<YWX:+Q_9X!@[( +MF";*]N9_-X\?Z:FG'X=_(C+BCJ8FCJ[2&CN/C^\_7U__OZ.KRS*>?FY>!DXR +MSD[*(^IKSY^O$U\_FQO38]KZ^XHBRJNZHNHJ6EH*BH+:BSLC@V.S\Z.KJJKB +M$C*R[F[B>AIJ^WMKNV,;JBO+JXJKB^L+HWN+&UM+RYL;NPL[2^LJ*NJ*2DH* +M:DH**NK*:HNK^II*2CK*"KI**NJ**@L+B[L;>[N;XUM[&]N;2PN+JPJZ^IHB +MHIJ:FLJJ*^L+2TL+J^JZ.@K*BJNK:_L;VQN;>TN+J^IJ*BJJJJKJBDK*:@JZ +MRNKJ:JIKBVL+2TL+"VOKJRHJ*@K*BBJJ*\N[.YL;VWN+*DK:XF+B6IKZZ@M+ +M^Z/C>_O+JLKZ.@H*"JIKRPL+BPL+BXNKZNHK:PN+Z^NJ"DK*2CJZB@K*:NN+ +MZPN[.[M+BZLJJRKJBHJ*:JLK"TL+^SL+*^LKZ@K*2LH*BFKJJZNJ"@JKJRN+ +M:VOKZ^MKBVNK*JHK:PN+:XMK*^IJB@K*NDH*BFKJJZLKZZNKJBOKBTM+2TN[ +M2VLK*HH*RKHZ2NKKZZOKBVMK:XN+ZROKJZJJZBHK*FHJ"DI*RFJK:\N[^_M[ +M2VNJ:DI*NOHZ"BHKRSO[.[M+"^NJZNKJ:NHJZBJJ*XO+B^NKJBKJ:FKJ:HIJ +MZJHK*ZHJJJHJJZJJJRLKJZOK*^KJBVL+N\M+RPN+BVMK:^OKJ^JJJBIJBLJZ +MRHJ*:NHK"\M+"XOKJZOKJVJJJBHJZFJ*ZFIJ*BJJJJMK:^O+N\L+2TOKJJKJ +MBBKJ:@IJZ@J*BZLJZVLK*JOK*RMKJZMKZZJJ*^H*J@LKVX]Z#FHB[KH+HBM# +M>QO#6[O;FVN[NZJJZGK:RKHZ:FKJBVOKJ^NJZPN*JFNJNCJJ.GKJ2ZNKNRL: +MVA*NQ\D^GF?.)B\WGF[#SE(+BU)[HX+O_](NHXZ>"TH.4P<*6J>+LN]+CBKB +MKBOJ^PKO)Z-O$QO2.KI>4C(N#MIJ2EOO@R^/DZ,[J^+:RJ)*0CJ:2DMK(RM+ +MXRK;ZNJJBNLZ*AK*"CH+BZL+"[O+:TN[FRO+:VHZNBI*:FMJZNM+ZJIKJFJ+ +M:BJKRBHJ*GHK*DJJRROJRQN;J[I+"VN+JRL[*XI+NPJK>ZL*BXOZFGHBHIH: +MRNI*:WO##^NK0RHBZ@NNFKM:^OMKRLMCBSM;&WL+*PIJRLKJRDK*NFN+ZVO[ +M6\LKBXLKRJJKNIH**ZNJZFJ*"HI*:NL*^NM+"@I;6ZJJ(R.KZUNCZCI+.Z*" +M:DOJXBH;JR+JPPOBZJ.J8NH+BLN[:BL[*^K[VZMK^XOJ*BKJZBKZ.JJ*.FHK +MRCIKJMIJBVH*BHKKNZLK8]L*.W-[:B,SNMI[.T(BXVORNIN*,JO;RFJ+ZRNK +MBJ*[`RK[KY-K2Z\[XGHJ^M(R`C("@EJJ&_OK@],;BWN;&A+:BIK:*WM+J^H+ +M>ZJZNW,;J@,O*_*[<SI"&Q/ZXEM[2B(*"YKNKDHK2BIS_X_S+].[2GHR;HY. +M_NY"0J+[<ULCTY-;2]L;ZXIJJPHZJLM[.WMC`R/CXSNJBGHBVKI:KJ[:HI*" +M._L"&B,SR^N#$W,[.GOORZ[KGWM.VO,:WE(#8[M3_U_?DVO+RXYF/NZF9HZB +MLEKK(Z]3`W-O\ZOKFZIBVFL+NQO;,[.;>S,3R^M[B_KR;@YNCKXN@@+BJWL; +M$P^OKT_/6[OC2SHZZGK:RHK:\J*#+S-OOX\#Z\IR+L[>'CZ.CA(J:\M;0_,# +MPZ/;&XMKBXNJBCN;^]NCXYL+JRHJJ\L[^VLJJ@H:\A+NCN[NPDJ*RHH#TX.S +M;X]#@V,;&SOJ2JOJ,M)Z8Y,OOT\_[\L"[@XF9B:F_@Y""MNO+V\/CQ.;BRLZ +MLC(:2BH+^P/S,S/S,R.;ZXJJ^_L+2ZJZ8A*.O@[.#J[BRJK[8Y./#V^/#_,[ +M^PLZ8F*2TMK[[P_/_]_/F\K";A[F9B:>OHYBRR-C4^]ODYN["ZNZ6KHKBPO; +M,Y,S@P-#XSNKRLIZ(F(:ZXNJJLL+2CHZ.EH2+NY20C("&NN;P^\//S_/[Z^O +M8RKZ(L*NKN)K6]OC<R_S^^IZ6JZ^_KZ.#@Z2>JM+X_,O[Q.3,X.;"RMJ:LHZ +M"JL+:RMKR_O[N\L+"VNKJBHJJRHJ:GJB@F)B8H(B^FKK2YM;XV,C6Z,CFSM+ +M"^KZ.IH:^LHJZXN+:ZNK.YN;HZ.;BVHZ>GIZ&OHZ^KKJ*RLJBLKZ^CKZN@HJ +MJJL+.QNC8[,SHYM[^[O+2RKJ:DH*2CKZ2@H*R@KJZJHKZVOKZRNKZNKJ"LJZ +M.KH**VLK"[M+BXMKBRNJJZOK:VOK:RLKZPN[.[N[NTOKJZJK:HKJ"CHZ2LH* +MZJHJ*BHJZJHJ:NIJRHJ**NJJJ^MK*^L+^WM[.[L[2[N[N[N[NXMJFOHZFOKZ +MN@IJ*PM+RVOKJRIJ"@J**BKJZJKKZVN+2\N+"PL+BRLK*BKJ*BKJ*NKJJBLK +M*XL+:^NJJFIJZJHK*ZNJ*VOKJBHJ:HJ*"FIJZBOK:JHKJBN+BXO+2[L[2TM+ +M"^NJB@J*R@IJ:FJJJZNJJNMK*ZNJ:@H*:BLK*ZNK*ZNKZXN+ZRLK*ZJJJBMK +M*RNKJZNJJBJKJBJJJJNJJ^N+BRO+NPMK*ZJJ*BIJBBJJ*HH*:NJJJROK*ZJJ +MJFM+RPJZNJJ["SLJ*@I*:FJJJDN[.TL+ZXOKJZJJ"@J*ZBOKZRNKJJJJZHIJ +MBBKJ"FJJ*VL[^XO+RXN+*RNK:^NJ*LH*"@IJ:JJJJJNKJJHJ*JMKZXMKJRMK +M*RMK*ZJK:VOK*NJK*ZLJ*JHK:VNKJBIJBHJJZXL+BVMKJJHJ*JNK*ZOJZHJ* +M"PO+2XLKJ^JJ*ZLJ:FJ*BHKJJJLKBZLJ*BHK:XMKZZNJJBMK"XOKZ^NKJZLK +MJZNKJRLKJRHJJJIJ"HHJ*BJKJRKJ*JJK*^LKBPL+"VN+2TLKZXLKZ^N*NMH: +MFOKKFVJZNRMJBPMCHPO;VZJ+JOKK.CKKFCJJNKKJJVLKRRL+"XOJ2BIJ*PH[ +M.]J#Z@I;.DMK*BIKZPI;HAM;(@.Z>KM*LB,J4N_R>M.N`]OR[V*JKP[OXTX_ +MJG[''FHGAC_K_C_N^O/N(YO.#^K.7V[JOZ9_ROX'C@+?;OH/WN\C/C]"RF\. +M:K]^:T^.:QO*N\*O*J[ORXYOJLXGCBL/OF.+XN,B8]HK&S)[BR+;*]K#"]H[ +MZT*OBE+O2U)3B@*[&A/"4N>F6W,^?Q++4X+J\[J2([MR:V\N&M-Z6H,;+A-[ +M#L\K#G\BKG_20C,:HK-KPG,JZQN"(Z.^D^_FDV^^>[OC[FMO#ON[FBL;,L/C +MCD^+K@\BHT*S:S)C:FJ+`NHC<NK+8PZJ7WX2=V9:)Z+^7TJNL_HO#M-S+EL; +MPAN"XPK"LP+B3XX"OQ*:$QK:[ZYJ9V9SWZ9_6J)?AG-/9N\*BUHK@QIBKVHJ +MBWI;2^(3@CI3#N,:$D,J8J_R>J>.*V]R>UM*RINZ&T)S*[XG@@Z'YD//)H,3 +M/BHOHM)[+P*N+_-^;X(32[Y_XR9/`YX/HH(/XHX'?NZW'L(G[H(?KJ)O[@I_ +M)N._IGLO4OKSZF*O^OH#DE/*$@^+KNMOVDY_>B)#,C/ZTM.C_OLG7D('TGX_ +M8PYKBU-*[D,/\E*/KV8[YQZ.Y[H^SSH;DIN#RG(Z![::=W;;I[[KDY+C3X:? +M^Z;O#R8*YT(2>Z,J<EI?+JY/ZHY#RN)OOK,?AF,G)FH_LN+/CO-;KH,#\JI3 +M[GMO/KHG9BM?GDH?9D^OAB_?QEM?9@^+@H.;SH\+OJ=R3N<BOJ=B(@_R>A\F +M"U_F8P]NBY^F>H=&\__VYVOFI[O>[_\&IW/&-_*F-^Y>MPZ^)RX2IXZNAQXJ +M;ZX[:^K;FOH3Z[Z?:QX_2RZORRYCN[*+LS)#BP*S^Y*JFX+KJWI*(WJ[.HHC +M"CK+KXZKGT)B0^LJ*XHJ\\)BWRYN?VJ^;VLN4ZJ"C^(NGYN&/S,F?_+"[X+B +MPRHR;]+KCSY#DRZC,^[S(R)J$]*[[TY38_YO^TZC0Y[S.Q[OZW);6V(;&^YO +M:KZG^LZG\H(_DL(/NI+?;JIOK@OO8HO+.BO[XNX?$@X/*A(36NY?@N[_8DIO +M[DOOLKHK+U)KV[(O^N[O:JY/.N[/"P[3*@*K\V+;:[K;J_NN<Z-.OQO>WRL. +M0_NN2VJKZBZ/\B)O$FJ_?EM?9H,/;OLKFI-R2U,*:C-JFL].:B^"KK,K6GIK +M2_*SJ@*O^C*_&BX?`HZ?\G(3K@NO7G_;7J>:;@>.ZB>F+T_F_TJ.7VZB+\Z[ +MRVZ#0FNKFGN+VKN;"G.:^[/:\VNNW[YZGV8CNSZ/>JY3XLI;ZLHCRCMK6TOB +M4RL:0^(*DX+*P]K[`QJ;F@N+@GM:PM/*8CNBJHKZR[(Z^[K;^GK/2W*?@I*G +M\CKS4B,CXDM[J^H#ZF(JVVK"VZLRLXORBPH",]IB,ZN::UORBUNZJJJJ8VNZ +M^TN+BR,+&AN;*J)*N[H*JXI*2PK+BM+;FUI;"AKS*KN;XKL[JBM*NDL+Z@H* +M*\M*ZXJJ6ZJ[2DK;.HM*(LO*2VJZ&^HC.XJ[NAO[^JKK*@O+*RK*JZKZNHK+ +MBBHK:JN+*NHKZ^L+*BI+J@N+ZCLKBDO*ZNL*BRH*BRJJ"XNKZJOKJFHJJFO+ +M"XMKJJNJ:BL+ZBIJRHJZRHJK"^LKJZHK:[O+2_O+ZZJKJ^JK*FHJBFJ*2HJJ +MBJHKJDN[:VNKBPOJJJNJBVNK*@H*ZFJ*BNHKZPN+*^LKJBLJ*JLJJXN+JNJJ +MJRIJ*JJKBPMK2TN+BVMK*VIJRDH*BLJZ"LJ**ROKBRL+R^MK:^L+"XLK*NKJ +M*VO+"XOKJFH*BBHK*ZJJ*^IJ:HIJZNHJ*JKKBRNKZHKK2XN+B^NJBFJKZTM+ +M:ZNJJBHJB@JJJBOKJZN+RXLJ"FIJ*BOK:PL+*XI*RBHK*^OK:PMKJZKK:\M+ +M:RLJ"LH*BJOKZ^NJJNJ*"HKJ*FN+B^N*JNLK:XM+RVNK:FHJJFL+:RLKZHIJ +MZJKK:RLJZFIJZJJKJBKJ*BNK:XN+"VLK:NHK:\L+*RJ*2HHJ*\M+2XOJ:BJJ +MJZLJ:FIJ:FHJ*RLJJJH**LL+"\MKZZLJ*VMK*RJ*BNJKZXMK*ZHJZJJJ*ROJ +MBHJ**BMK"XOK*ZNKZVL+RPLKJZJJ*RLKZZHJ:@H*BNHJJZLJ*NKJ*JOKZ^OK +MZPOK*FL+*^LKJRMK:VLKZHH*:JJJJ^MKZZNJ*JLKJVMK:VOKZRNKJBHJ:NHJ +M*NHJ*BHJJJNK*^MK:^OK:^MK:^LKJJLKJJLKJRNKJ^MKZZKJZJMKZNJJJBHJ +MJNKJ*JJJJJJJJZHJJZOKZ^MK:^LK*ZNJJJOK:XN+:VMK:^LK*RNKJBHJ*BHJ +M*BKJZNIJZBKJJBOKZZNKJJJJJZNJ*JOKZVL+*RIK:ZLK*ZNKJRLKJZOKZVOK +MZ^LKJZKJBFIJZBHJ*BHJ*JHK*VN+:^OKJZHJJJJJJRLKJRNKJJJK:PN+:^LK +MJJKJ:@H*BJKK*^N+BVOKJRIKBRJJJBHJ*NKJ:JHKJZNKJBJJZBHK:XN+Z^OK +MZZJK*RLK*ZJJ*FKJJJLK*^LKJ^LKJZLKJZKJZBJKJJJKJRMKZZNK*ZNJ*NKJ +MJJHJJZHK:RJ*JJIJ*JNK*RLK:^MKBVMKBXMK:^LKJFJ*BHIJZNKJ*JJJJZJK +MZ^OK:^LKZ^OKJZJJ*NKJ*BKJZBN+:^MK:^OKB^OKBVNKJBHJ*BIJ:FJ*Z^OJ +MJBNKJZNJ*JHKZ^MK*ZNJ*BJJJ^OKZ^OKZRNKJZLKJZJKJZNJJBKJZBHJBFJJ +MJRLKJRMKBXN+:RLK*RNK*^OK*ZNK*NHJZNHJ*JJJJ^OJ"JNJJBLKJZIK:VOK +MZVOK*RLKJFIJBHIJ*BKJ*JOKBPO+BVMKZRNJ*JOKZZNKJNKJ*BJJ*ZHJ*BJK +MJRJJJRJJJBIJZJHKZ^OKZVN+B^NKJHMKJFMKJZNK*BJJJZNKJRKJZNKJ*BLK +MZXOK*ZKJZNJ*BFKJJNOKZ^MK:VOKZVOKZ^LKJZLJ:FHJ*BJJ*^LKZ^MKZZLJ +M*JHJ:FJ*BBHK*PO+ZZN+ZZNK*ZNJ*JJJ*BJJJBHJJBLK:ZNJJBMKZRLK*ZNK +MZVOKJZNK*BJKJZJJJZNJJJJKJZJJ:FKJ*JJKJRNKJJOK*ZLKJZLK*RLK*ZLK +M*RL+:VJJJJJJ*ROKZ^LK*^LKJZNK*RNK*FKJZBJJJBJJ*BHJZBJJ*BHJJNKJ +MJBOKZRLK:PL+RPN+ZRNK*ZKJBNHJ*BHJJBHJJJNJ*JJK:XL+BRKJZZOJ*NKJ +M:BHJJJLKZVN+"XMKZVOK*RHJ:@K*:JKK:RNKJRJJJRN+R\OK*RNJZNKJJJNJ +MZFKJ*BJJJROK*ZHJ*NKJJZNKJZLKZXL+BROKRROJJZKJ*NIJBFHJ*BJJ*^MK +MBVOKJROK:VOK*ZKJZNKJ*JJKJZHJ*JJJJRLK*^OKZ^OKJZNK*RLK*ZHJ:HJ* +MBHHJJRLKJZLKZVLKZVMK"PNJ*XMKZVLK*BKJZFJ*:HJ*BFHJJROKZRNK*RLK +M:XMKZ^OKJZIJ:BJJJ^MKZ^MKZ^OKZROK:VLKZHIJ:HJ*ZNKJZNHJJROK:XL+ +M"\L+BXLK*POKZBIJ"HIJB@H*BNJJJRLK*ZNKJRMK:VMKRTO+BXN+ZZLJZBKJ +M:NKJ:FHJJBJKJZJKJZHJJJHK:VOK*ZJJ*^OK:XMK*ZNK*NKJ*BKJZBHJRFKK +MZ^N+BPO+"VLK*ZHJZNIJ:NKJJJNK*RNJ*JLKJZLK*ZLKZRLK*RNK*ZNJJRHJ +M*FKJ*JJJZ^OKBPN+:^NKJJJJJJNJJJL+2VN*HH+:R@M[BVKJJ^N+NTO+"XLK +M:PN+ZRIJ:FKJ:NIJ:JKKBXO+BXN+BRLJZBJJJFIJZJJK*RNKJJKJ:NKJ:FIJ +M*BMKZ^OKBPO+"VLK*BHK*VMKBVLKJ@KJZRHJJBHJJ^NK*RNKJRLK*ZHJ*JHK +M*ZHJZHJ*BFJKBXOKJZNK:VL+"PN+JZHJZJHKZ^LKJRKJ:FIJZBIJ:NJK:XN+ +M:RNJJBHJZ^OKJXJJRVOK"POKZZMJBFHJ*JNK*NHJJJNKJZJKZRLK*RNKJRKJ +M:NHJJZNJJJJKZVN+"\M+R\MK*^LKJZIJ"HIJZBJJJNIJBHHJJRNKZVOK:VL+ +M2TLK*VLJ*BNKJBIJ"LI*2@KJJJJJ*FIJZBN+N_M[^TMKZROK*^OK*^OK:XMK +M*RIJ2KI*RHJ*RLI*2DH*ZNKJZNJJB\O[&WO[NTM+"PN+:RNKZXNJBJHJ:FIJ +MBHKJ*NHJZNJJJZOKZZNKJZJJJJLK*RNJ*BJK:VMKZZNK*NKJ*JOKZZIJZJJK +M*ROKZ^MK"\M+2PMKJ^K*2@IJ*NHJJZHKZXMK*BNJRNJKZZNKZXMK*RLKZVNK +MJBIJZJHK*^NK*JJJ*BHK*^NJZFJ*ZJJK*VL+BVMKZ^MK:^NJJBKJ*BHJZFJ* +M:BHJJJNK*JOK*^OK*RNKZJO+ZVO+ZZJJJJJK*^OKJZHJZBJJ*RLKJZNKJ^MK +MBXOKJFJ*"@J*BNKJZNJJ*ZOK:VMKZVL+RTM+2\L+:RNKZ@H*2DJZ"NJJ*NJJ +MJROK:XMKZRHKBZLKZRLK*ZNJ*JLKZ^LK*ZNJ*NJJ*JKKZRLKZZNJZFIJZBJJ +MJ^OK*RNK*RNKJZNKJBHJ*JNKJZJK*ZNJJBHJJJLK*RLK:^LKZZNKJRHKBZNJ +MZZHJ*ZNK*^OKZ^LK*ZHJJBLKJZNK*NKJZNHJJBJJJZLK*VL+"TN[RXOK*^LK +MJBJ*"FJ*"HKJ*BJKJ^OK:VOKJZJJ*JJJZHH**JLKZZJ**\N+"\N+BXN+BVMK +M*ZJJJBHJ*NKJZFKJB@IJZBJJJJJK*RLKZROK:VN+:RNKJRLKZVOK*ZNJ*BKJ +M*BHJZBJK*ROKZ^LKJRNKJBHJJRNKBPLK*^LK*NKJZNKJ*FKJ*JJK*^MK:^MK +MBVOKZ^LKJZNJJZLJ*JJKJRJJJJLKJZHJZNJJ*ZLK*^N+:ZNJJZNJJZNKJZNJ +MJJHJZBJJJ^N+BXLK:BHJBBJJJRNKJZJJ*^N+:^OKZZNJ*JOK:VNKJJHJ*BJJ +MJJJJ*NKJ*BJJJJHJJNLK*RNKJZLKZVN+BVOK*ZHJJJOKZRNJZBJJ*BKJZBJJ +M*NL+*NJJZBJJ*JHKZ^OK:ROKZXL+B^NK*NJJ*RNKJNHJ:@K*RLJ*ZBJK:PN[ +M^WM[^[N+ZZLJZNHJJJHJ*BHJZNIJBNHJJJLKJZHJJNKJJJJK*HJJJRHK:VL+ +M2[N[.SO+"^LKJZNK:LJZ.DJZ2HKJZBHJ*BJJ*^MK2TN[NTO+BRLK*ZLJZNIJ +M:BHJ*BHJ*BHJZFHJJBLKZVL+B^OKZZJKJJO+2RLK*^KJZBKJ*BKJ:NKJZJHJ +M*JHKZ^N+:VOKZXN+RPO+RVOKJRKJ:NIJBHIJ:FIJZJLKJRLK*^LKJZJK*ROK +MZVMK:VLKJRHJZFIJZBJJJVI*JBOKR\M+N\N+Z^LKJRHJ*NIJBHHJJBHJ*BIJ +MZJHKZ^LK*ZHJJJOKZ^LK*^LKJBKJJJNJJZLKZRLK*ZNJ*RMKBXMKZRNJ*BKJ +M*BIJBHIJ*^LJJRNJJBOKBXOK*ZHJJJKKBVNKJJJJJJNJ*RNJ*NJ*:JLKZRNK +M*BJJZXN+:XMK:PN+:XMKZROKJNKJZNHJJNJ*BHIJ*BKJ*JJJJJOK:^OJ"JOK +M:TL[N[O+BVOK*RNKJNJ*"FHJ*BIJ*BHJ*BKJ*NKJZNJJ*^LKZ^OK*ROKB\N[ +MNXN+ZZLK*ZLJZNIJ:FHJ*FH*RLK*2HJKZVMKZROKB_N;R\N+*ZHKJRIJ:FKJ +M*NHJJZNKJJHJ*BJJJJOK*ZLKJ^MKZVOKJNKJJ^MK:^LK*ZNJ*ZLK*RNJ*XN+ +M"XLKJFH*"FJ*"FIJBNKJJROKZVO+*ZH+"XO+RVNKJJJJJRNKJJKJ:NIJ:NKJ +M*BHJJBL+R\N+ZZNJJJOK*RLJJJKJZHIJJBLK*ZNJ*^OKZRNJ*FIJZJJKZVOK +MJNHJJNMKZZNK*BK+NVL+BRNK*HIJZBKJBFKJ:FHJ*^LK*JLK"\M+RPMKJFIJ +MBNKJ*NHJJ^MK*^OKJZLKJZNKJZNKJNHJJRLKJNHJZNIJ:NKJ:FHJZXL[^WL[ +M2RN*JJNJZRNK*FJ*BNJJZRNJZHH*BNJK*FJ*ZJOKBPO+"^NKJZOK:PO+BZLJ +MZFKJJ^NKJJIJBNIJ*JJKJZLKZRLKZVOK*ZLK*RHJ*FIJJZOKBVMKBXLKZ^LJ +MB@KJ:HHJZNJJ*XMKZRMKBPO+R\N+*RHJZFIJJJLJ:HH*ZJJKZ^OK:RNK*JJJ +M*JHJJJHJJJOK:VN+R\MKZRNJ*JLK*ZLKZROJBBIJ:BKJ:HJJ*RLKJZNKJZJK +M*ZLK*ROKJ^HJZNJJ*ROK"XOK*ZKJ*JNKJNKJ*BHJZXO+RXN+BVLK*RNKJRIJ +M:FKJZJKJ*BHJZFHJJJJJJXOKJXMKB^OK*ZNKJRLK*^NKJ^LKZROKJZNJJJOK +M*RNJZNJ*"FHJJNKJJBOKJJNKJRLKJZHKBXMK"PN+Z^OKZ^NJJZNJZHH*R@H* +M:JMK:VMKZNIKJZOKB\N[2\N+:ROJB@K*"LH*BHIJ*BLK*ROK"TN+BXL+ZRNK +MJ@I*2KI*BBJK*VL+2\O+RXMK*ZNK*BJJJBIJ:FHJ*JMK:RNKJJLKZVN[BZJJ +M:LJ*ZBJJJZLJJBJJJ^L+:^LKJRLK:VN+:RNK*JJJ*JHK*ZIJZJJJJZNK*RLK +M:^OKZZOJ:LH*:NJJJJNJJRNK*^MK:VOK:XO+"PL+Z\JZRLH*:NJK*ZNKJJHK +MJRIJ*JJK*VL+RXMKJZJJZ^OK:VLKJNJJ*FJ*"@H*:FJJZPL+BXLKJRMK*^OK +MZZLK*^N+*ZJK*NKJZBJK*^J*"@HJBRNK:VOK*ZNJJROKZ^NKJBOK:^LKJZIJ +M"@J*:JJKJZJKJJJK*ROK:VMKZXO+R\L+*ZIJRDH*BNJJJZLJJJNKJBHJ*JJK +M*ZLKJZLJ:BHKBVNK"TOKZVMKBVLK*NKJ*JJKJRNKZRNKJZHJ:HH*"NJJZRNJ +M*BHJJJMKBVMK:VMKBPN+BXOKJJJJ*BJJZNH*RLH*ZJOK:VOK*VMKBPMK*RKJ +MJFNJZJNJ*NH*"HKJ*^MKBPMK*ROKZROKZRNJ:HH*BBJK*RLKJBLK*RLK*^N+ +M"XOKJJNKJJLKJZLKJNH*R@IJJBN+"\L+:RNK*RLKJZNJZBKJRFJK*JIKZROK +MZ^MKJ^KJJJJKZXO+BVLKJBJ*:NKJ*JHJ*BIJZHJJZRMK:XMKZ^MKBPO+"XOK +MJNH*RFIJ:NKJZBJJJJLKJJNJJ^OK:XOKZPN[*XJ*:BHKJZNK*NKJ*JOK:RNJ +MZFHJ*BJKZPN+BVOKJZNKJRNJJBJKZ^OKJJKK:RNJZNKJ:FJ*ZJJJJJNJJJJK +M*RLKJROK:\M+2TL+*RIJROK**FHJJJJK:VMKZ^LKJZNK*^MKZZNJ*FH*"@J* +MBFJJJJJJJJN+R[O+BPL+"XOK:VLKJVJ*:@K*B@H*"NJKZ^MK:XN+:^LKZVOK +M*RHJ*BIKRRNJJVIJ:FHJ*JHJZNHJJ^MKBXN+:RNJJJOKBPN+*ZNJJJNKJ^H* +M2DH*BFKJ*JJKZVMK"PO+2TM+B^NK*NIJBHH*"BJJJZHJ*JHK:PL+:ZL**BNK +M:^OK:RNJ*BHJJJHJZNKJZBHKBVLK*BJK*^MKBVOK*RMK*ZLJ:BJJ*NIJ:FIJ +M:JLK*^OKBXN+"XMKBXN+:^NK*FJ*:FKJ*RNKJBKJ*NLJJNLK*RNJJ^OK*RLK +MZFKJZBHKJZNKJJJKZPN+BROJZFHJ*JJK*^NJJ^N+2PN+JRJJ*JJKZRLJZFKJ +M*JHJJNNK*ZLJJFNK*JMJZNKJZXNJ*HN[RPN[2\OKJXJZ"OJ**NJJ*VKJ\V,^ +M,L_K:+AW"5^_#F+'J1OF2,C?F>GJH]>NR.BHI\X>0M=W#AHK:3<OP@IF_M[& +MIA9>*O_7J9=/>VH#?X;V]C8NVRY;WSKO-S='#J;:4R]#>@ZO_L+B+OJ2D[L* +MYC:CJ4D7B^:FSNLK+I9HABN/-U?GTW.;XZI"IG9N2ML#AX?:\UM*"KH/^W+2 +M7HX+"A+.C\?G;YJ^YB:RJVN?XV-;[Z>[;H9>"B\;;E(*\_\'8^)Z(HNZ"P*2 +M+CI#L^\#Z^Z"+P^#GHXK&RJB^FO;JL/G>S)2.NL^GJ:"LY,/?Q_/^C(B>O+N +M"ELJDT]O8UK*HNNJ&KON'HYSAZ\[,CNJKJK2&JH+\QN[>HK[FVI"`D):FX_; +MVLO;BCM#V_LZXJZNNZ_3>D*CHW-S&G(ZLPOR"AIB0@*#+Y-3$QK2DD)RVNK: +MJW-/+SM*BYL"[@XB"HK#LYM:^W-3+ZO2(NL;&TJ:>KN#&^MZ>FO*BKMJ(J(; +M&]JBZHO[JTJ:JHO*ZN(*(\.[:]O;V]LZZUO[JOK*XA+2:X.;^_LKJZM*XDIS +M,]K::DL+"AH::XIJZP,CJ]HZ,^/JZKKK:AI"+N)JFSOC$]O#`RO*"COZRKK: +M(J++JZI+PV/[^\NKJZH*(NMKV@IJRB+:*YL["RNZB@IKNQOJRHOKP^.+BKJ+ +MBVNK^LKJ*ZHZ2@MJ.LO+"LM+B^L+6RL*"OIJZ^HZBR-;2_K:^J*BFHHKNP,S +M(ZN+ZOH:>BL[:RJK.WN+ZGJ:^FO;NPNJ:OO[>\JZ&LJ[2EH:*VLJN_N+"@KK +MJZIKJRMKZPMK*ZLKJLJJJBJ+RYOKJRKJ:@JZ.NM[ZCKKRSN[NZIJJVN+:@K* +MRF(.+@*:*@M[6^-C@X-CXZ/;F_N[RXOKJRKJ:HH*"LK*2DI*RLK*R@H*BHIJ +MZBHJJJJKJRLKZ^OKZ^OK:^MKZ^LKZRLK*RLK*ZLKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +GJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK +` +end diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 6730a07..ba4d97b 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.519 1998/12/27 14:21:08 sos Exp $ +# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1533,7 +1533,121 @@ device iicsmb0 at iicbus? controller pcf0 at isa? port 0x320 net irq 5 +# ISDN4BSD section + +# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver) +# note that the ``options'' and ``device'' lines must BOTH be defined ! +# +# Non-PnP Cards: +# -------------- +# +# Teles S0/8 or Niccy 1008 +options "TEL_S0_8" +#device isic0 at isa? iomem 0xd0000 net irq 5 flags 1 vector isicintr +# +# Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 +options "TEL_S0_16" +#device isic0 at isa? port 0xd80 iomem 0xd0000 net irq 5 flags 2 vector isicintr +# +# Teles S0/16.3 +options "TEL_S0_16_3" +#device isic0 at isa? port 0xd80 net irq 5 flags 3 vector isicintr +# +# AVM A1 or AVM Fritz!Card +options "AVM_A1" +#device isic0 at isa? port 0x340 net irq 5 flags 4 vector isicintr +# +# USRobotics Sportster ISDN TA intern +options "USR_STI" +#device isic0 at isa? port 0x268 net irq 5 flags 7 vector isicintr +# +# ITK ix1 Micro +options "ITKIX1" +#device isic0 at isa? port 0x398 net irq 10 flags 18 vector isicintr +# +# PnP-Cards: +# ---------- +# +# Teles S0/16.3 PnP +options "TEL_S0_16_3_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Creatix ISDN-S0 P&P +options "CRTX_S0_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dr. Neuhaus Niccy Go@ +options "DRN_NGO" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Sedlbauer Win Speed +options "SEDLBAUER" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dynalink IS64PH +options "DYNALINK" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# ELSA QuickStep 1000pro ISA +options "ELSA_QS1ISA" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# PCI-Cards: +# ---------- +# +# ELSA QuickStep 1000pro PCI +options "ELSA_QS1PCI" +#device isic0 # +# PCMCIA-Cards: +# ------------- +# +# AVM PCMCIA Fritz!Card +options "AVM_A1_PCMCIA" +device isic0 at isa? port 0x340 net irq 5 flags 10 vector isicintr +# +# Active Cards: +# ------------- +# +# Stollmann Tina-dd control device +device tina0 at isa? port 0x260 net irq 10 vector tinaintr +# +# ISDN Protocol Stack +# ------------------- +# +# Q.921 / layer 2 - i4b passive cards D channel handling +pseudo-device "i4bq921" +# +# Q.931 / layer 3 - i4b passive cards D channel handling +pseudo-device "i4bq931" +# +# layer 4 - i4b common passive and active card handling +pseudo-device "i4b" +# +# ISDN devices +# ------------ +# +# userland driver to do ISDN tracing (for passive cards only) +pseudo-device "i4btrc" 4 +# +# userland driver to control the whole thing +pseudo-device "i4bctl" +# +# userland driver for access to raw B channel +pseudo-device "i4brbch" 4 +# +# userland driver for telephony +pseudo-device "i4btel" 2 +# +# network driver for IP over raw HDLC ISDN +pseudo-device "i4bipr" 4 +# enable VJ header compression detection for ipr i/f +options IPR_VJ +# +# network driver for sync PPP over ISDN +pseudo-device "i4bisppp" 4 + + # Parallel-Port Bus # # Parallel port bus support is provided by the `ppbus' device. diff --git a/sys/conf/files b/sys/conf/files index 2830546..cc4e8e7 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -199,6 +199,42 @@ gnu/ext2fs/ext2_lookup.c optional ext2fs gnu/ext2fs/ext2_subr.c optional ext2fs gnu/ext2fs/ext2_vfsops.c optional ext2fs gnu/ext2fs/ext2_vnops.c optional ext2fs +# device drivers +i4b/driver/i4b_trace.c optional i4btrc device-driver +i4b/driver/i4b_rbch.c optional i4brbch device-driver +i4b/driver/i4b_tel.c optional i4btel device-driver +i4b/driver/i4b_ipr.c optional i4bipr +i4b/driver/i4b_ctl.c optional i4bctl device-driver +i4b/driver/i4b_isppp.c optional i4bisppp device-driver +net/if_spppsubr.c optional sppp +# needed by i4bipr +net/slcompress.c optional i4bipr +# tina-dd control driver +i4b/tina-dd/i4b_tina_dd.c optional tina device-driver +# support +i4b/layer2/i4b_mbuf.c optional i4btrc device-driver +# Q.921 handler +i4b/layer2/i4b_l2.c optional i4bq921 +i4b/layer2/i4b_l2fsm.c optional i4bq921 +i4b/layer2/i4b_uframe.c optional i4bq921 +i4b/layer2/i4b_tei.c optional i4bq921 +i4b/layer2/i4b_sframe.c optional i4bq921 +i4b/layer2/i4b_iframe.c optional i4bq921 +i4b/layer2/i4b_l2timer.c optional i4bq921 +i4b/layer2/i4b_util.c optional i4bq921 +i4b/layer2/i4b_lme.c optional i4bq921 +# Q.931 handler +i4b/layer3/i4b_q931.c optional i4bq931 +i4b/layer3/i4b_l3fsm.c optional i4bq931 +i4b/layer3/i4b_l3timer.c optional i4bq931 +i4b/layer3/i4b_l2if.c optional i4bq931 +i4b/layer3/i4b_l4if.c optional i4bq931 +i4b/layer3/i4b_q932fac.c optional i4bq931 +# isdn device driver, interface to i4bd +i4b/layer4/i4b_i4bdrv.c optional i4b device-driver +i4b/layer4/i4b_l4.c optional i4b device-driver +i4b/layer4/i4b_l4mgmt.c optional i4b device-driver +i4b/layer4/i4b_l4timer.c optional i4b device-driver isofs/cd9660/cd9660_bmap.c optional cd9660 isofs/cd9660/cd9660_lookup.c optional cd9660 isofs/cd9660/cd9660_node.c optional cd9660 diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index e32ce13..cbc1a26 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.213 1998/12/27 13:55:48 sos Exp $ +# $Id: files.i386,v 1.214 1998/12/27 14:21:08 sos Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -195,6 +195,30 @@ i386/linux/linux_stats.c optional compat_linux i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux i386/linux/linux_util.c optional compat_linux +i4b/layer1/i4b_isic.c optional isic device-driver +i4b/layer1/i4b_isic_isa.c optional isic device-driver +i4b/layer1/i4b_isic_pnp.c optional isic device-driver +i4b/layer1/i4b_isic_pci.c optional isic device-driver +i4b/layer1/i4b_isic_pcmcia.c optional isic device-driver +i4b/layer1/i4b_isac.c optional isic device-driver +i4b/layer1/i4b_hscx.c optional isic device-driver +i4b/layer1/i4b_l1.c optional isic device-driver +i4b/layer1/i4b_l1fsm.c optional isic device-driver +i4b/layer1/i4b_bchan.c optional isic device-driver +i4b/layer1/i4b_tel_s08.c optional isic device-driver +i4b/layer1/i4b_tel_s016.c optional isic device-driver +i4b/layer1/i4b_tel_s0163.c optional isic device-driver +i4b/layer1/i4b_tel_s0P.c optional isic device-driver +i4b/layer1/i4b_ctx_s0P.c optional isic device-driver +i4b/layer1/i4b_avm_a1.c optional isic device-driver +i4b/layer1/i4b_avm_fritz_pcmcia.c optional isic device-driver +i4b/layer1/i4b_usr_sti.c optional isic device-driver +i4b/layer1/i4b_itk_ix1.c optional isic device-driver +i4b/layer1/i4b_drn_ngo.c optional isic device-driver +i4b/layer1/i4b_sws.c optional isic device-driver +i4b/layer1/i4b_dynalink.c optional isic device-driver +i4b/layer1/i4b_elsa_qs1i.c optional isic device-driver +i4b/layer1/i4b_elsa_qs1p.c optional isic device-driver libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard diff --git a/sys/conf/options.i386 b/sys/conf/options.i386 index e1b95b9..4604c9a 100644 --- a/sys/conf/options.i386 +++ b/sys/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.97 1998/12/27 13:36:44 phk Exp $ +# $Id: options.i386,v 1.98 1998/12/27 14:21:08 sos Exp $ DISABLE_PSE IDE_DELAY @@ -102,3 +102,39 @@ FDC_YE opt_fdc.h # Video spigot SPIGOT_UNSECURE opt_spigot.h +# ------------------------------- +# isdn4bsd: passive ISA cards +# ------------------------------- +TEL_S0_8 opt_i4b.h +TEL_S0_16 opt_i4b.h +TEL_S0_16_3 opt_i4b.h +AVM_A1 opt_i4b.h +USR_STI opt_i4b.h +ITKIX1 opt_i4b.h +# ------------------------------- +# isdn4bsd: passive ISA PnP cards +# ------------------------------- +CRTX_S0_P opt_i4b.h +DRN_NGO opt_i4b.h +TEL_S0_16_3_P opt_i4b.h +SEDLBAUER opt_i4b.h +DYNALINK opt_i4b.h +ELSA_QS1ISA opt_i4b.h +# ------------------------------- +# isdn4bsd: passive PCI cards +# ------------------------------- +ELSA_QS1PCI opt_i4b.h +# ------------------------------- +# isdn4bsd: passive PCMCIA cards +# ------------------------------- +AVM_A1_PCMCIA opt_i4b.h +# ------------------------------- +# isdn4bsd: misc options +# ------------------------------- +# temporary workaround for SMP machines +I4B_SMP_WORKAROUND opt_i4b.h +# enable VJ compression code for ipr i/f +IPR_VJ opt_i4b.h +# ------------------------------- +# EOF +# ------------------------------- diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 6730a07..ba4d97b 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.519 1998/12/27 14:21:08 sos Exp $ +# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1533,7 +1533,121 @@ device iicsmb0 at iicbus? controller pcf0 at isa? port 0x320 net irq 5 +# ISDN4BSD section + +# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver) +# note that the ``options'' and ``device'' lines must BOTH be defined ! +# +# Non-PnP Cards: +# -------------- +# +# Teles S0/8 or Niccy 1008 +options "TEL_S0_8" +#device isic0 at isa? iomem 0xd0000 net irq 5 flags 1 vector isicintr +# +# Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 +options "TEL_S0_16" +#device isic0 at isa? port 0xd80 iomem 0xd0000 net irq 5 flags 2 vector isicintr +# +# Teles S0/16.3 +options "TEL_S0_16_3" +#device isic0 at isa? port 0xd80 net irq 5 flags 3 vector isicintr +# +# AVM A1 or AVM Fritz!Card +options "AVM_A1" +#device isic0 at isa? port 0x340 net irq 5 flags 4 vector isicintr +# +# USRobotics Sportster ISDN TA intern +options "USR_STI" +#device isic0 at isa? port 0x268 net irq 5 flags 7 vector isicintr +# +# ITK ix1 Micro +options "ITKIX1" +#device isic0 at isa? port 0x398 net irq 10 flags 18 vector isicintr +# +# PnP-Cards: +# ---------- +# +# Teles S0/16.3 PnP +options "TEL_S0_16_3_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Creatix ISDN-S0 P&P +options "CRTX_S0_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dr. Neuhaus Niccy Go@ +options "DRN_NGO" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Sedlbauer Win Speed +options "SEDLBAUER" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dynalink IS64PH +options "DYNALINK" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# ELSA QuickStep 1000pro ISA +options "ELSA_QS1ISA" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# PCI-Cards: +# ---------- +# +# ELSA QuickStep 1000pro PCI +options "ELSA_QS1PCI" +#device isic0 # +# PCMCIA-Cards: +# ------------- +# +# AVM PCMCIA Fritz!Card +options "AVM_A1_PCMCIA" +device isic0 at isa? port 0x340 net irq 5 flags 10 vector isicintr +# +# Active Cards: +# ------------- +# +# Stollmann Tina-dd control device +device tina0 at isa? port 0x260 net irq 10 vector tinaintr +# +# ISDN Protocol Stack +# ------------------- +# +# Q.921 / layer 2 - i4b passive cards D channel handling +pseudo-device "i4bq921" +# +# Q.931 / layer 3 - i4b passive cards D channel handling +pseudo-device "i4bq931" +# +# layer 4 - i4b common passive and active card handling +pseudo-device "i4b" +# +# ISDN devices +# ------------ +# +# userland driver to do ISDN tracing (for passive cards only) +pseudo-device "i4btrc" 4 +# +# userland driver to control the whole thing +pseudo-device "i4bctl" +# +# userland driver for access to raw B channel +pseudo-device "i4brbch" 4 +# +# userland driver for telephony +pseudo-device "i4btel" 2 +# +# network driver for IP over raw HDLC ISDN +pseudo-device "i4bipr" 4 +# enable VJ header compression detection for ipr i/f +options IPR_VJ +# +# network driver for sync PPP over ISDN +pseudo-device "i4bisppp" 4 + + # Parallel-Port Bus # # Parallel port bus support is provided by the `ppbus' device. diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 6730a07..ba4d97b 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.519 1998/12/27 14:21:08 sos Exp $ +# $Id: LINT,v 1.520 1998/12/27 19:51:34 phk Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -1533,7 +1533,121 @@ device iicsmb0 at iicbus? controller pcf0 at isa? port 0x320 net irq 5 +# ISDN4BSD section + +# i4b passive ISDN cards support (isic - I4b Siemens Isdn Chipset driver) +# note that the ``options'' and ``device'' lines must BOTH be defined ! +# +# Non-PnP Cards: +# -------------- +# +# Teles S0/8 or Niccy 1008 +options "TEL_S0_8" +#device isic0 at isa? iomem 0xd0000 net irq 5 flags 1 vector isicintr +# +# Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 +options "TEL_S0_16" +#device isic0 at isa? port 0xd80 iomem 0xd0000 net irq 5 flags 2 vector isicintr +# +# Teles S0/16.3 +options "TEL_S0_16_3" +#device isic0 at isa? port 0xd80 net irq 5 flags 3 vector isicintr +# +# AVM A1 or AVM Fritz!Card +options "AVM_A1" +#device isic0 at isa? port 0x340 net irq 5 flags 4 vector isicintr +# +# USRobotics Sportster ISDN TA intern +options "USR_STI" +#device isic0 at isa? port 0x268 net irq 5 flags 7 vector isicintr +# +# ITK ix1 Micro +options "ITKIX1" +#device isic0 at isa? port 0x398 net irq 10 flags 18 vector isicintr +# +# PnP-Cards: +# ---------- +# +# Teles S0/16.3 PnP +options "TEL_S0_16_3_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Creatix ISDN-S0 P&P +options "CRTX_S0_P" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dr. Neuhaus Niccy Go@ +options "DRN_NGO" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Sedlbauer Win Speed +options "SEDLBAUER" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# Dynalink IS64PH +options "DYNALINK" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# ELSA QuickStep 1000pro ISA +options "ELSA_QS1ISA" +#device isic0 at isa? port ? net irq ? vector isicintr +# +# PCI-Cards: +# ---------- +# +# ELSA QuickStep 1000pro PCI +options "ELSA_QS1PCI" +#device isic0 # +# PCMCIA-Cards: +# ------------- +# +# AVM PCMCIA Fritz!Card +options "AVM_A1_PCMCIA" +device isic0 at isa? port 0x340 net irq 5 flags 10 vector isicintr +# +# Active Cards: +# ------------- +# +# Stollmann Tina-dd control device +device tina0 at isa? port 0x260 net irq 10 vector tinaintr +# +# ISDN Protocol Stack +# ------------------- +# +# Q.921 / layer 2 - i4b passive cards D channel handling +pseudo-device "i4bq921" +# +# Q.931 / layer 3 - i4b passive cards D channel handling +pseudo-device "i4bq931" +# +# layer 4 - i4b common passive and active card handling +pseudo-device "i4b" +# +# ISDN devices +# ------------ +# +# userland driver to do ISDN tracing (for passive cards only) +pseudo-device "i4btrc" 4 +# +# userland driver to control the whole thing +pseudo-device "i4bctl" +# +# userland driver for access to raw B channel +pseudo-device "i4brbch" 4 +# +# userland driver for telephony +pseudo-device "i4btel" 2 +# +# network driver for IP over raw HDLC ISDN +pseudo-device "i4bipr" 4 +# enable VJ header compression detection for ipr i/f +options IPR_VJ +# +# network driver for sync PPP over ISDN +pseudo-device "i4bisppp" 4 + + # Parallel-Port Bus # # Parallel port bus support is provided by the `ppbus' device. diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index e32ce13..cbc1a26 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.213 1998/12/27 13:55:48 sos Exp $ +# $Id: files.i386,v 1.214 1998/12/27 14:21:08 sos Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -195,6 +195,30 @@ i386/linux/linux_stats.c optional compat_linux i386/linux/linux_sysent.c optional compat_linux i386/linux/linux_sysvec.c optional compat_linux i386/linux/linux_util.c optional compat_linux +i4b/layer1/i4b_isic.c optional isic device-driver +i4b/layer1/i4b_isic_isa.c optional isic device-driver +i4b/layer1/i4b_isic_pnp.c optional isic device-driver +i4b/layer1/i4b_isic_pci.c optional isic device-driver +i4b/layer1/i4b_isic_pcmcia.c optional isic device-driver +i4b/layer1/i4b_isac.c optional isic device-driver +i4b/layer1/i4b_hscx.c optional isic device-driver +i4b/layer1/i4b_l1.c optional isic device-driver +i4b/layer1/i4b_l1fsm.c optional isic device-driver +i4b/layer1/i4b_bchan.c optional isic device-driver +i4b/layer1/i4b_tel_s08.c optional isic device-driver +i4b/layer1/i4b_tel_s016.c optional isic device-driver +i4b/layer1/i4b_tel_s0163.c optional isic device-driver +i4b/layer1/i4b_tel_s0P.c optional isic device-driver +i4b/layer1/i4b_ctx_s0P.c optional isic device-driver +i4b/layer1/i4b_avm_a1.c optional isic device-driver +i4b/layer1/i4b_avm_fritz_pcmcia.c optional isic device-driver +i4b/layer1/i4b_usr_sti.c optional isic device-driver +i4b/layer1/i4b_itk_ix1.c optional isic device-driver +i4b/layer1/i4b_drn_ngo.c optional isic device-driver +i4b/layer1/i4b_sws.c optional isic device-driver +i4b/layer1/i4b_dynalink.c optional isic device-driver +i4b/layer1/i4b_elsa_qs1i.c optional isic device-driver +i4b/layer1/i4b_elsa_qs1p.c optional isic device-driver libkern/bcd.c standard libkern/divdi3.c standard libkern/inet_ntoa.c standard diff --git a/sys/i386/conf/options.i386 b/sys/i386/conf/options.i386 index e1b95b9..4604c9a 100644 --- a/sys/i386/conf/options.i386 +++ b/sys/i386/conf/options.i386 @@ -1,4 +1,4 @@ -# $Id: options.i386,v 1.97 1998/12/27 13:36:44 phk Exp $ +# $Id: options.i386,v 1.98 1998/12/27 14:21:08 sos Exp $ DISABLE_PSE IDE_DELAY @@ -102,3 +102,39 @@ FDC_YE opt_fdc.h # Video spigot SPIGOT_UNSECURE opt_spigot.h +# ------------------------------- +# isdn4bsd: passive ISA cards +# ------------------------------- +TEL_S0_8 opt_i4b.h +TEL_S0_16 opt_i4b.h +TEL_S0_16_3 opt_i4b.h +AVM_A1 opt_i4b.h +USR_STI opt_i4b.h +ITKIX1 opt_i4b.h +# ------------------------------- +# isdn4bsd: passive ISA PnP cards +# ------------------------------- +CRTX_S0_P opt_i4b.h +DRN_NGO opt_i4b.h +TEL_S0_16_3_P opt_i4b.h +SEDLBAUER opt_i4b.h +DYNALINK opt_i4b.h +ELSA_QS1ISA opt_i4b.h +# ------------------------------- +# isdn4bsd: passive PCI cards +# ------------------------------- +ELSA_QS1PCI opt_i4b.h +# ------------------------------- +# isdn4bsd: passive PCMCIA cards +# ------------------------------- +AVM_A1_PCMCIA opt_i4b.h +# ------------------------------- +# isdn4bsd: misc options +# ------------------------------- +# temporary workaround for SMP machines +I4B_SMP_WORKAROUND opt_i4b.h +# enable VJ compression code for ipr i/f +IPR_VJ opt_i4b.h +# ------------------------------- +# EOF +# ------------------------------- diff --git a/sys/i386/include/i4b_cause.h b/sys/i386/include/i4b_cause.h new file mode 100644 index 0000000..439db4e --- /dev/null +++ b/sys/i386/include/i4b_cause.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_cause.h - causes and cause handling for i4b + * ----------------------------------------------- + * + * $Id: i4b_cause.h,v 1.8 1998/12/05 18:05:55 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:30 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_CAUSE_H_ +#define _I4B_CAUSE_H_ + +/*---------------------------------------------------------------------------* + * ISDN4BSD internal causes specification + *---------------------------------------------------------------------------*/ + +#define CAUSE_VAL 0x000000ff /* cause value */ +#define CAUSE_TYPE 0x0000ff00 /* cause type */ +#define CAUSET_Q850 0 /* value coded according to Q.850 */ +#define CAUSET_I4B 1 /* i4b protocol independent causes*/ + +#define GET_CAUSE_VAL(cause) ((cause) & 0xff) +#define SET_CAUSE_VAL(dest, val) ((dest) = ((dest & 0xffffff00) | \ + (val & 0x000000ff))) + +#define GET_CAUSE_TYPE(cause) (((cause) >> 8) & 0xff) +#define SET_CAUSE_TYPE(dest, type) ((dest) = ((dest & 0xffff00ff) | \ + ((type << 8) & 0x0000ff00))) + +#define SET_CAUSE_TV(dest, type, val) ((dest) = ((val & 0x000000ff) | \ + ((type << 8) & 0x0000ff00))) + +/* CAUSET_I4B - protocol independent cause values */ + +#define CAUSE_I4B_NORMAL 0 /* normal call clearing */ +#define CAUSE_I4B_BUSY 1 /* user busy */ +#define CAUSE_I4B_NOCHAN 2 /* circuit/channel not available*/ +#define CAUSE_I4B_INCOMP 3 /* incompatible source/dest */ +#define CAUSE_I4B_REJECT 4 /* call rejected */ +#define CAUSE_I4B_OOO 5 /* destination out of order */ +#define CAUSE_I4B_TMPFAIL 6 /* temporary failure */ +#define CAUSE_I4B_L1ERROR 7 /* L1 error / persistent deact */ +#define CAUSE_I4B_MAX 8 + +/* CAUSET_Q850 - causes defined in Q.850 */ + +#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */ +#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */ +#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */ +#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */ +#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */ +#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */ +#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */ +#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */ +#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */ +#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */ +#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */ +#define CAUSE_Q850_USRBSY 0x11 /* User busy */ +#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */ +#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */ +#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */ +#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */ +#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */ +#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */ +#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */ +#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */ +#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */ +#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */ +#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */ +#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */ +#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */ +#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */ +#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */ +#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */ +#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */ +#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */ +#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */ +#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */ +#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */ +#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */ +#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */ +#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */ +#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */ +#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */ +#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */ +#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */ +#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */ +#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */ +#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */ +#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */ +#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */ +#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */ +#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */ +#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */ +#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */ +#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */ +#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */ +#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */ +#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */ +#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */ +#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */ +#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */ +#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */ +#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */ +#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */ +#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */ +#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */ +#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */ +#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */ +#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */ +#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */ +#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */ +#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */ +#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */ + +#define CAUSE_Q850_MAX 128 + +#endif /* _I4B_CAUSE_H_ */ diff --git a/sys/i386/include/i4b_debug.h b/sys/i386/include/i4b_debug.h new file mode 100644 index 0000000..33e6315 --- /dev/null +++ b/sys/i386/include/i4b_debug.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_debug.h - i4b debug header file + * ----------------------------------- + * + * $Id: i4b_debug.h,v 1.14 1998/12/05 18:05:57 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:47 1998] + * + *---------------------------------------------------------------------------*/ + +#define DO_I4B_DEBUG /* enable debugging code inclusion */ + +#undef DO_I4B_MAXDEBUG /* enable ALL debug messages by default */ + +#ifdef DO_I4B_DEBUG + +extern unsigned int i4b_l1_debug; +extern unsigned int i4b_l2_debug; +extern unsigned int i4b_l3_debug; +extern unsigned int i4b_l4_debug; + +#define DBGL1(bits, routine, what) \ + if(bits & i4b_l1_debug) \ + { \ + printf("i4b-L1-%s: ", routine); \ + printf what ; \ + } + +#define DBGL2(bits, routine, what) \ + if(bits & i4b_l2_debug) \ + { \ + printf("i4b-L2-%s: ", routine); \ + printf what ; \ + } + +#define DBGL3(bits, routine, what) \ + if(bits & i4b_l3_debug) \ + { \ + printf("i4b-L3-%s: ", routine); \ + printf what ; \ + } + +#define DBGL4(bits, routine, what) \ + if(bits & i4b_l4_debug) \ + { \ + printf("i4b-L4-%s: ", routine); \ + printf what ; \ + } +#else /* !DO_I4B_DEBUG */ + +#define DBGL1(bits, routine, what); +#define DBGL2(bits, routine, what); +#define DBGL3(bits, routine, what); +#define DBGL4(bits, routine, what); + +#endif /* DO_I4B_DEBUG */ + +/* Layer 1 */ + +#define L1_ERROR 0x0001 /* general error message*/ +#define L1_PRIM 0x0002 /* interlayer primitives*/ +#define L1_BCHAN 0x0004 /* B channel action */ +#define L1_H_ERR 0x0008 /* HSCX errors */ +#define L1_H_IRQ 0x0010 /* HSCX IRQ messages */ +#define L1_I_ERR 0x0020 /* ISAC errors */ +#define L1_I_MSG 0x0040 /* ISAC messages */ +#define L1_I_SETUP 0x0080 /* ISAC setup messages */ +#define L1_F_MSG 0x0100 /* FSM messages */ +#define L1_F_ERR 0x0200 /* FSM error messages */ +#define L1_T_MSG 0x0400 /* Timer messages */ +#define L1_T_ERR 0x0800 /* Timer error messages */ +#define L1_H_XFRERR 0x1000 /* HSCX data xfer error */ +#define L1_I_CICO 0x2000 /* ISAC command in/out */ + +#define L1_DEBUG_MAX 0x3fef /* all messages on except IRQ! */ +#define L1_DEBUG_ERR (L1_H_ERR | L1_I_ERR | L1_F_ERR | L1_T_ERR | L1_ERROR) + +#ifndef L1_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L1_DEBUG_DEFAULT L1_DEBUG_MAX +#else +#define L1_DEBUG_DEFAULT L1_DEBUG_ERR +#endif +#endif + +/* Layer 2 */ + +#define L2_ERROR 0x0001 /* general error message */ +#define L2_PRIM 0x0002 /* interlayer primitives */ +#define L2_U_MSG 0x0004 /* U frame messages */ +#define L2_U_ERR 0x0008 /* U frame error messages */ +#define L2_S_MSG 0x0010 /* S frame messages */ +#define L2_S_ERR 0x0020 /* S frame error messages */ +#define L2_I_MSG 0x0040 /* I frame messages */ +#define L2_I_ERR 0x0080 /* I frame error messages */ +#define L2_F_MSG 0x0100 /* FSM messages */ +#define L2_F_ERR 0x0200 /* FSM error messages */ +#define L2_T_MSG 0x0400 /* timer messages */ +#define L2_T_ERR 0x0800 /* timer error messages */ +#define L2_TEI_MSG 0x1000 /* TEI messages */ +#define L2_TEI_ERR 0x2000 /* TEI error messages */ + +#define L2_DEBUG_MAX 0x3fff /* all messages on */ +#define L2_DEBUG_ERR (L2_ERROR | L2_I_ERR | L2_F_ERR | L2_T_ERR | L2_S_ERR | L2_TEI_ERR | L2_U_ERR ) + +#ifndef L2_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L2_DEBUG_DEFAULT L2_DEBUG_MAX +#else +#define L2_DEBUG_DEFAULT L2_DEBUG_ERR +#endif +#endif + +/* Layer 3 */ + +#define L3_ERR 0x0001 /* general error message */ +#define L3_MSG 0x0002 /* general message */ +#define L3_F_MSG 0x0004 /* FSM messages */ +#define L3_F_ERR 0x0008 /* FSM error messages */ +#define L3_T_MSG 0x0010 /* timer messages */ +#define L3_T_ERR 0x0020 /* timer error messages */ +#define L3_P_MSG 0x0040 /* protocol messages */ +#define L3_P_ERR 0x0080 /* protocol error messages */ +#define L3_A_MSG 0x0100 /* AOC messages */ +#define L3_A_ERR 0x0200 /* AOC error messages */ +#define L3_PRIM 0x0400 /* messages exchanged */ + +#define L3_DEBUG_MAX 0x07ff /* all messages on */ +#define L3_DEBUG_ERR (L3_ERR | L3_F_ERR | L3_T_ERR | L3_P_ERR | L3_A_ERR) + +#ifndef L3_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L3_DEBUG_DEFAULT L3_DEBUG_MAX +#else +#define L3_DEBUG_DEFAULT L3_DEBUG_ERR +#endif +#endif + +/* Layer 4 */ + +#define L4_ERR 0x0001 /* general error message */ +#define L4_MSG 0x0002 /* general message */ +#define L4_TIMO 0x0004 /* b channel idle timeout msgs */ +#define L4_DIALST 0x0008 /* network driver dial states */ +#define L4_IPRDBG 0x0010 /* ipr driver debug messages */ +#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */ + +#define L4_DEBUG_MAX 0x003f /* all messages on */ +#define L4_DEBUG_ERR (L4_ERR) + +#ifndef L4_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L4_DEBUG_DEFAULT L4_DEBUG_MAX +#else +#define L4_DEBUG_DEFAULT L4_DEBUG_ERR +#endif +#endif + +/*---------------------------------------------------------------------------* + * ioctl via /dev/i4bctl: + * get/set current debug bits settings + *---------------------------------------------------------------------------*/ + +typedef struct { + unsigned int l1; + unsigned int l2; + unsigned int l3; + unsigned int l4; +} ctl_debug_t; + +#define I4B_CTL_GET_DEBUG _IOR('C', 0, ctl_debug_t) + +#define I4B_CTL_SET_DEBUG _IOW('C', 1, ctl_debug_t) + +/*---------------------------------------------------------------------------* + * get hscx statistics + *---------------------------------------------------------------------------*/ + +typedef struct { + int unit; /* controller number */ + int chan; /* channel number */ + int vfr; + int rdo; + int crc; + int rab; + int xdu; + int rfo; +} hscxstat_t; + +#define I4B_CTL_GET_HSCXSTAT _IOWR('C', 2, hscxstat_t) + +#define I4B_CTL_CLR_HSCXSTAT _IOW('C', 3, hscxstat_t) + +/* EOF */ diff --git a/sys/i386/include/i4b_ioctl.h b/sys/i386/include/i4b_ioctl.h new file mode 100644 index 0000000..17e945f --- /dev/null +++ b/sys/i386/include/i4b_ioctl.h @@ -0,0 +1,606 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ioctl.h - messages kernel <--> userland + * ------------------------------------------- + * + * $Id: i4b_ioctl.h,v 1.58 1998/12/22 19:48:24 hm Exp $ + * + * last edit-date: [Tue Dec 22 20:33:46 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_IOCTL_H_ +#define _I4B_IOCTL_H_ + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#ifndef _MACHINE_TYPES_H_ +#include <machine/types.h> +#endif /* _MACHINE_TYPES_H_ */ +#endif /* __FreeBSD__ */ + +/*---------------------------------------------------------------------------* + * version and release number for isdn4bsd package + *---------------------------------------------------------------------------*/ +#define VERSION 0 /* version number */ +#define REL 70 /* release number */ +#define STEP 00 /* release step */ + +/*---------------------------------------------------------------------------* + * date/time format in i4b log messages + * ------------------------------------ + * Being year 2000 clean is not easy with the current state of the + * ANSI C library standard and it's implementation for some locales. + * You might like to use the "%c" format of "strftime" sometimes, + * but this breaks Y2K in some locales. Also the old standard logfile + * format "%d.%m.%y %H:%M:%S" is non compliant. + * NetBSD's current toolset warns about this problems, and we compile + * with -Werror, so this problems need to be resolved. + *---------------------------------------------------------------------------*/ +#define I4B_TIME_FORMAT "%d.%m.%Y %H:%M:%S" + +/*---------------------------------------------------------------------------* + * max number of controllers in system + *---------------------------------------------------------------------------*/ +#define MAX_CONTROLLERS 8 /* max number of controllers */ + +/*---------------------------------------------------------------------------* + * controller types + *---------------------------------------------------------------------------*/ +#define CTRL_INVALID (-1) /* invalid, error */ +#define CTRL_UNKNOWN 0 /* unknown controller type */ +#define CTRL_PASSIVE 1 /* passive ISDN controller cards*/ +#define CTRL_DAIC 2 /* Diehl active controller cards*/ +#define CTRL_NUMTYPES 3 /* number of controller types */ + +/*---------------------------------------------------------------------------* + * card types for CTRL_PASSIVE + *---------------------------------------------------------------------------*/ +#define CARD_TYPEP_INVAL (-1) /* invalid, error */ +#define CARD_TYPEP_UNK 0 /* unknown */ +#define CARD_TYPEP_8 1 /* Teles, S0/8 */ +#define CARD_TYPEP_16 2 /* Teles, S0/16 */ +#define CARD_TYPEP_16_3 3 /* Teles, S0/16.3 */ +#define CARD_TYPEP_AVMA1 4 /* AVM A1 or AVM Fritz!Card */ +#define CARD_TYPEP_163P 5 /* Teles, S0/16.3 PnP */ +#define CARD_TYPEP_CS0P 6 /* Creatix, S0 PnP */ +#define CARD_TYPEP_USRTA 7 /* US Robotics ISDN TA internal */ +#define CARD_TYPEP_DRNNGO 8 /* Dr. Neuhaus Niccy GO@ */ +#define CARD_TYPEP_SWS 9 /* Sedlbauer Win Speed */ +#define CARD_TYPEP_DYNALINK 10 /* Dynalink IS64PH */ +#define CARD_TYPEP_BLMASTER 11 /* ISDN Blaster / ISDN Master */ +#define CARD_TYPEP_PCFRITZ 12 /* AVM PCMCIA Fritz!Card */ +#define CARD_TYPEP_ELSAQS1ISA 13 /* ELSA QuickStep 1000pro ISA */ +#define CARD_TYPEP_ELSAQS1PCI 14 /* ELSA QuickStep 1000pro PCI */ +#define CARD_TYPEP_SIEMENSITALK 15 /* Siemens I-Talk */ +#define CARD_TYPEP_ELSAMLIMC 16 /* ELSA MicroLink ISDN/MC */ +#define CARD_TYPEP_ELSAMLMCALL 17 /* ELSA MicroLink MCall */ +#define CARD_TYPEP_ITKIX1 18 /* ITK ix1 micro */ + +/* + * in case you add support for more cards, please update: + * + * isdnd: support.c, name_of_controller() + * diehl/diehlctl: main.c, listall() + * + * and adjust CARD_TYPEP_MAX below. + */ + +#define CARD_TYPEP_MAX 18 /* max type */ + +/*---------------------------------------------------------------------------* + * card types for CTRL_DAIC + *---------------------------------------------------------------------------*/ +#define CARD_TYPEA_DAIC_UNK 0 +#define CARD_TYPEA_DAIC_S 1 +#define CARD_TYPEA_DAIC_SX 2 +#define CARD_TYPEA_DAIC_SCOM 3 +#define CARD_TYPEA_DAIC_QUAD 4 + +/*---------------------------------------------------------------------------* + * max length of some strings + *---------------------------------------------------------------------------*/ +#define TELNO_MAX 41 /* max length of a telephone number (+ '\0') */ +#define DISPLAY_MAX 91 /* max length of display information (+ '\0') */ +#define DATETIME_MAX 21 /* max length of datetime information (+ '\0')*/ + +/*---------------------------------------------------------------------------* + * in case the src or dst telephone number is empty + *---------------------------------------------------------------------------*/ +#define TELNO_EMPTY "NotAvailable" + +/*---------------------------------------------------------------------------* + * B channel parameters + *---------------------------------------------------------------------------*/ +#define BCH_MAX_DATALEN 2048 /* max length of a B channel frame */ + +/*---------------------------------------------------------------------------* + * userland driver types + * --------------------- + * a "driver" is defined here as a piece of software interfacing an + * ISDN B channel with a userland service, such as IP, Telephony etc. + *---------------------------------------------------------------------------*/ +#define BDRV_RBCH 0 /* raw b-channel interface driver */ +#define BDRV_TEL 1 /* telephone (speech) interface driver */ +#define BDRV_IPR 2 /* IP over raw HDLC interface driver */ +#define BDRV_ISPPP 3 /* sync Kernel PPP interface driver */ + +/*---------------------------------------------------------------------------* + * B channel protocol + *---------------------------------------------------------------------------*/ +#define BPROT_NONE 0 /* no protocol at all, raw data */ +#define BPROT_RHDLC 1 /* raw HDLC: flag, data, crc, flag */ + +/*---------------------------------------------------------------------------* + * causes data type + *---------------------------------------------------------------------------*/ +typedef unsigned int cause_t; /* 32 bit unsigned int */ + +/*---------------------------------------------------------------------------* + * call descriptor id (cdid) definitions + *---------------------------------------------------------------------------*/ +#define CDID_UNUSED 0 /* cdid is invalid and unused */ +#define CDID_MAX 99999 /* highest valid cdid, wraparound to 1 */ + + +/**************************************************************************** + + outgoing call: + -------------- + + userland kernel + -------- ------ + + CDID_REQ -----------------> + + <------------------ cdid + + CONNECT_REQ --------------> + + <------------------ PROCEEDING_IND (if connect req ok) + + <------------------ CONNECT_ACTIVE_IND (if connection ok) + + or + + <------------------ DISCONNECT_IND (if connection failed) + + + + incoming call: + -------------- + + userland kernel + -------- ------ + + <------------------ CONNECT_IND + + CONNECT_RESP -------------> + + <------------------ CONNECT_ACTIVE_IND (if accepted) + + + + active disconnect: + ------------------ + + userland kernel + -------- ------ + + DISCONNECT_REQ ------------> + + <------------------ DISCONNECT_IND + + + passive disconnect: + ------------------- + + userland kernel + -------- ------ + + <------------------ DISCONNECT_IND + + +****************************************************************************/ + + +/*===========================================================================* + *===========================================================================* + * "read" messages from kernel -> userland + *===========================================================================* + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * message header, included in every message + *---------------------------------------------------------------------------*/ +typedef struct { + char type; /* message identifier */ +#define MSG_CONNECT_IND 'a' +#define MSG_CONNECT_ACTIVE_IND 'b' +#define MSG_DISCONNECT_IND 'c' +#define MSG_DIALOUT_IND 'd' +#define MSG_IDLE_TIMEOUT_IND 'e' +#define MSG_ACCT_IND 'f' +#define MSG_CHARGING_IND 'g' +#define MSG_PROCEEDING_IND 'h' +#define MSG_ALERT_IND 'i' +#define MSG_DRVRDISC_REQ 'j' +#define MSG_L12STAT_IND 'k' +#define MSG_TEIASG_IND 'l' +#define MSG_PDEACT_IND 'm' +#define MSG_NEGCOMP_IND 'n' +#define MSG_IFSTATE_CHANGED_IND 'o' + int cdid; /* call descriptor id */ +} msg_hdr_t; + +/*---------------------------------------------------------------------------* + * connect indication + * indicates incoming connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number */ + int channel; /* channel number */ +#define CHAN_B1 0 /* this _must_ be 0, HSCX B1 is also 0 */ +#define CHAN_B2 1 /* this _must_ be 1, HSCX B2 is also 1 */ +#define CHAN_ANY (-1) /* outgoing, not possible for incoming */ +#define CHAN_NO (-2) /* call waiting (CW) for incoming */ + int bprot; /* b channel protocot, see BPROT_XXX */ + char dst_telno[TELNO_MAX]; /* destination telno */ + char src_telno[TELNO_MAX]; /* source telno */ + int scr_ind;/* screening indicator */ +#define SCR_NONE 0 /* no screening indicator transmitted */ +#define SCR_USR_NOSC 1 /* screening user provided, not screened*/ +#define SCR_USR_PASS 2 /* screening user provided, verified & passed */ +#define SCR_USR_FAIL 3 /* screening user provided, verified & failed */ +#define SCR_NET 4 /* screening network provided */ + char display[DISPLAY_MAX]; /* content of display IE*/ +} msg_connect_ind_t; + +/*---------------------------------------------------------------------------* + * connect active indication + * indicates active connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number actually used */ + int channel; /* channel number actually used */ + char datetime[DATETIME_MAX]; /* content of date/time IE */ +} msg_connect_active_ind_t; + +/*---------------------------------------------------------------------------* + * disconnect indication + * indicates a disconnect + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + cause_t cause; /* cause code */ +} msg_disconnect_ind_t; + +/*---------------------------------------------------------------------------* + * negotiation complete + * indicates an interface is completely up & running + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_negcomplete_ind_t; + +/*---------------------------------------------------------------------------* + * interface changes internal state + * indicates an interface has somehow switched its FSM + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int state; /* new interface state */ +} msg_ifstatechg_ind_t; + +/*---------------------------------------------------------------------------* + * initiate a call to a remote site + * i.e. the IP driver got a packet and wants a connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int driver; /* driver type */ + int driver_unit; /* driver unit number */ +} msg_dialout_ind_t; + +/*---------------------------------------------------------------------------* + * idle timeout disconnect sent indication + * kernel has sent disconnect request because of b-ch idle + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_idle_timeout_ind_t; + +/*---------------------------------------------------------------------------* + * accounting information from userland interface driver to daemon + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int accttype; /* accounting type */ +#define ACCT_DURING 0 +#define ACCT_FINAL 1 + int driver; /* driver type */ + int driver_unit; /* driver unit number */ + int ioutbytes; /* ISDN # of bytes sent */ + int iinbytes; /* ISDN # of bytes received */ + int outbps; /* bytes per sec out */ + int inbps; /* bytes per sec in */ + int outbytes; /* driver # of bytes sent */ + int inbytes; /* driver # of bytes received */ +} msg_accounting_ind_t; + +/*---------------------------------------------------------------------------* + * charging information from isdn driver to daemon + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int units; /* number of units */ + int units_type; /* type of units info */ +#define CHARGE_INVALID 0 /* invalid, unknown */ +#define CHARGE_AOCD 1 /* advice of charge during call */ +#define CHARGE_AOCE 2 /* advice of charge at end of call */ +#define CHARGE_CALC 3 /* locally calculated from rates information */ +} msg_charging_ind_t; + +/*---------------------------------------------------------------------------* + * call proceeding indication + * indicates outgoing SETUP has been acknowleged + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number actually used */ + int channel; /* channel number actually used */ +} msg_proceeding_ind_t; + +/*---------------------------------------------------------------------------* + * alert indication + * indicates remote user side "rings" + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_alert_ind_t; + +/*---------------------------------------------------------------------------* + * driver requests to disconnect line + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int driver; /* driver type */ + int driver_unit; /* driver unit number */ +} msg_drvrdisc_req_t; + +/*---------------------------------------------------------------------------* + * state of layer 1/2 + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int layer; /* layer number (1/2) */ +#define LAYER_ONE 1 +#define LAYER_TWO 2 + int state; /* state info */ +#define LAYER_IDLE 0 +#define LAYER_ACTIVE 1 +} msg_l12stat_ind_t; + +/*---------------------------------------------------------------------------* + * TEI assignment messages + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int tei; /* TEI or -1 if invalid */ +} msg_teiasg_ind_t; + +/*---------------------------------------------------------------------------* + * persistent deactivation state of stack + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int numactive; /* number of active connections */ +} msg_pdeact_ind_t; + + +/*===========================================================================* + *===========================================================================* + * "ioctl" messages from userland -> kernel + *===========================================================================* + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * request a unique cdid (to setup an outgoing call) + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ +} msg_cdid_req_t; + +#define I4B_CDID_REQ _IOWR('4', 0, int) + +/*---------------------------------------------------------------------------* + * connect request + * requests an outgoing connection + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int controller; /* controller to use */ + int channel; /* channel to use */ + int txdelay; /* tx delay after connect */ + int bprot; /* b channel protocol */ + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int unitlen_time; /* length of a charging unit */ + int idle_time; /* time without activity on b ch */ + int earlyhup_time; /* safety area at end of unit */ + int unitlen_method; /* how to calculate the unitlength */ +#define ULEN_METHOD_STATIC 0 /* use unitlen_time value (see above) */ +#define ULEN_METHOD_DYNAMIC 1 /* use AOCD */ + char dst_telno[TELNO_MAX]; /* destination telephone no */ + char src_telno[TELNO_MAX]; /* source telephone number */ +} msg_connect_req_t; + +#define I4B_CONNECT_REQ _IOW('4', 1, msg_connect_req_t) + +/*---------------------------------------------------------------------------* + * connect response + * this is the answer to an incoming connect indication + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int response; /* what to do with incoming call */ +#define SETUP_RESP_DNTCRE 0 /* dont care, call is not for me */ +#define SETUP_RESP_REJECT 1 /* reject call */ +#define SETUP_RESP_ACCEPT 2 /* accept call */ + cause_t cause; /* cause for case SETUP_RESP_REJECT */ + /* the following are only used for SETUP_RESP_ACCEPT !! */ + int txdelay; /* tx delay after connect */ + int bprot; /* B chan protocol */ + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int max_idle_time; /* max time without activity on b ch */ +} msg_connect_resp_t; + +#define I4B_CONNECT_RESP _IOW('4', 2, msg_connect_resp_t) + +/*---------------------------------------------------------------------------* + * disconnect request + * active disconnect request + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + cause_t cause; /* protocol independent cause */ +} msg_discon_req_t; + +#define I4B_DISCONNECT_REQ _IOW('4', 3, msg_discon_req_t) + +/*---------------------------------------------------------------------------* + * controller info request + *---------------------------------------------------------------------------*/ +typedef struct { + int controller; /* controller number */ + int ncontroller; /* number of controllers in system */ + int ctrl_type; /* controller type passive/active */ + int card_type; /* brand / version */ + int tei; /* tei controller probably has */ +} msg_ctrl_info_req_t; + +#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t) + +/*---------------------------------------------------------------------------* + * dialout response + * status report to driver who requested a dialout + *---------------------------------------------------------------------------*/ +typedef struct { + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int stat; /* state of dialout request */ +#define DSTAT_NONE 0 +#define DSTAT_TFAIL 1 /* transient failure */ +#define DSTAT_PFAIL 2 /* permanent failure */ +#define DSTAT_INONLY 3 /* no outgoing dials allowed */ +} msg_dialout_resp_t; + +#define I4B_DIALOUT_RESP _IOW('4', 5, msg_dialout_resp_t) + +/*---------------------------------------------------------------------------* + * timeout value update + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int unitlen_time; /* length of a charging unit */ + int idle_time; /* time without activity on b ch */ + int earlyhup_time; /* safety area at end of unit */ +} msg_timeout_upd_t; + +#define I4B_TIMEOUT_UPD _IOW('4', 6, msg_timeout_upd_t) + +/*---------------------------------------------------------------------------* + * soft enable/disable + *---------------------------------------------------------------------------*/ +typedef struct { + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int updown; /* what to do */ +#define SOFT_ENA 0 /* enable interface */ +#define SOFT_DIS 1 /* disable interface */ +} msg_updown_ind_t; + +#define I4B_UPDOWN_IND _IOW('4', 7, msg_updown_ind_t) + +/*---------------------------------------------------------------------------* + * send alert request + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ +} msg_alert_req_t; + +#define I4B_ALERT_REQ _IOW('4', 8, msg_alert_req_t) + +/*---------------------------------------------------------------------------* + * request version and release info from kernel part + *---------------------------------------------------------------------------*/ +typedef struct { + int version; /* version number */ + int release; /* release number */ + int step; /* release step number */ +} msg_vr_req_t; + +#define I4B_VR_REQ _IOR('4', 9, msg_vr_req_t) + +/*---------------------------------------------------------------------------* + * Protocol download to active cards + *---------------------------------------------------------------------------*/ +struct isdn_dr_prot { + size_t bytecount; /* length of code */ + u_int8_t *microcode; /* pointer to microcode */ +}; + +struct isdn_download_request { + int controller; /* controller number */ + int numprotos; /* number of protocols in 'protocols' */ + struct isdn_dr_prot *protocols; +}; + +#define I4B_CTRL_DOWNLOAD _IOW('4', 100, struct isdn_download_request) + +/*---------------------------------------------------------------------------* + * Generic diagnostic interface for active cards + *---------------------------------------------------------------------------*/ +struct isdn_diagnostic_request { + int controller; /* controller number */ + u_int32_t cmd; /* diagnostic command to execute */ + size_t in_param_len; /* length of additional input parameter */ + void *in_param; /* optional input parameter */ + size_t out_param_len; /* available output space */ + void *out_param; /* output data goes here */ +}; + +#define I4B_ACTIVE_DIAGNOSTIC _IOW('4', 102, struct isdn_diagnostic_request) + +#endif /* _I4B_IOCTL_H_ */ diff --git a/sys/i386/include/i4b_tel_ioctl.h b/sys/i386/include/i4b_tel_ioctl.h new file mode 100644 index 0000000..b7f0f73 --- /dev/null +++ b/sys/i386/include/i4b_tel_ioctl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tel_ioctl.h telephony interface ioctls + * ------------------------------------------ + * + * $Id: i4b_tel_ioctl.h,v 1.5 1998/12/14 10:31:58 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:37:36 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_TEL_IOCTL_H_ +#define _I4B_TEL_IOCTL_H_ + +/* supported audio format conversions for /dev/i4btelXX devices */ + +#define CVT_NONE 0 /* no format conversion */ +#define CVT_ALAW2ULAW 1 /* kernel A-law, userland mu-law */ + +/*---------------------------------------------------------------------------* + * get / set audio format + *---------------------------------------------------------------------------*/ + +#define I4B_TEL_GETAUDIOFMT _IOR('A', 0, int) +#define I4B_TEL_SETAUDIOFMT _IOW('A', 1, int) +#define I4B_TEL_EMPTYINPUTQUEUE _IOW('A', 2, int) + +#endif /* _I4B_TEL_IOCTL_H_ */ diff --git a/sys/i386/include/i4b_trace.h b/sys/i386/include/i4b_trace.h new file mode 100644 index 0000000..07e08da --- /dev/null +++ b/sys/i386/include/i4b_trace.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_trace.h - header file for trace data read device + * ---------------------------------------------------- + * + * $Id: i4b_trace.h,v 1.5 1998/12/05 18:06:01 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:37:49 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_TRACE_H_ +#define _I4B_TRACE_H_ + +/*---------------------------------------------------------------------------* + * structure of the header at the beginning of every trace mbuf + *---------------------------------------------------------------------------*/ +typedef struct { + int length; /* length of the following mbuf */ + int unit; /* controller unit number */ + int type; /* type of channel */ +#define TRC_CH_I 0 /* Layer 1 INFO's */ +#define TRC_CH_D 1 /* D channel */ +#define TRC_CH_B1 2 /* B1 channel */ +#define TRC_CH_B2 3 /* B2 channel */ + int dir; /* direction */ +#define FROM_TE 0 /* user -> network */ +#define FROM_NT 1 /* network -> user */ + int trunc; /* # of truncated bytes (frame > MCLBYTES) */ + unsigned int count; /* frame count for this unit/type */ + struct timeval time; /* timestamp for this frame */ +} i4b_trace_hdr_t; + +#define INFO0 0 /* layer 1 */ +#define INFO1_8 1 +#define INFO1_10 2 +#define INFO2 3 +#define INFO3 4 +#define INFO4_8 5 +#define INFO4_10 6 + +/*---------------------------------------------------------------------------* + * ioctl via /dev/i4btrc device(s): + * get/set current trace flag settings + *---------------------------------------------------------------------------*/ + +#define I4B_TRC_GET _IOR('T', 0, int) /* get trace settings */ +#define I4B_TRC_SET _IOW('T', 1, int) /* set trace settings */ + +#define TRACE_OFF 0x00 /* tracing off */ +#define TRACE_I 0x01 /* trace L1 INFO's on */ +#define TRACE_D_TX 0x02 /* trace D channel on */ +#define TRACE_D_RX 0x04 /* trace D channel on */ +#define TRACE_B_TX 0x08 /* trace B channel on */ +#define TRACE_B_RX 0x10 /* trace B channel on */ + +typedef struct { + int rxunit; /* unit # for rx frames */ + int rxflags; /* d and/or b channel */ + int txunit; /* unit # for tx frames */ + int txflags; /* d and/or b channel */ +} i4b_trace_setupa_t; + +#define I4B_TRC_SETA _IOW('T', 2, i4b_trace_setupa_t) /* set analyze mode */ +#define I4B_TRC_RESETA _IOW('T', 3, int) /* reset analyze mode */ + +#endif /* _I4B_TRACE_H_ */ diff --git a/sys/i4b/driver/i4b_ctl.c b/sys/i4b/driver/i4b_ctl.c new file mode 100644 index 0000000..56bcb02 --- /dev/null +++ b/sys/i4b/driver/i4b_ctl.c @@ -0,0 +1,303 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ctl.c - i4b system control port driver + * ------------------------------------------ + * + * $Id: i4b_ctl.c,v 1.17 1998/12/05 18:02:39 hm Exp $ + * + * last edit-date: [Sat Dec 5 17:59:15 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4bctl.h" + +#if NI4BCTL > 1 +#error "only 1 (one) i4bctl device allowed!" +#endif + +#if NI4BCTL > 0 + +#include <sys/param.h> + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#include <i386/isa/isa_device.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/layer1/i4b_l1.h> + +static int openflag = 0; + +#if BSD > 199306 && defined(__FreeBSD__) +static d_open_t i4bctlopen; +static d_close_t i4bctlclose; +static d_ioctl_t i4bctlioctl; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +static d_poll_t i4bctlpoll; +#endif + +#define CDEV_MAJOR 55 +static struct cdevsw i4bctl_cdevsw = + { i4bctlopen, i4bctlclose, noread, nowrite, + i4bctlioctl, nostop, nullreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4bctlpoll, nommap, NULL, "i4bctl", NULL, -1 }; +#else + noselect, nommap, NULL, "i4bctl", NULL, -1 }; +#endif + +static void i4bctlattach(void *); +PSEUDO_SET(i4bctlattach, i4b_i4bctldrv); + +#define PDEVSTATIC static +#endif /* __FreeBSD__ */ + +#ifdef DEVFS +static void *devfs_token; +#endif + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* */ +void i4bctlattach __P((void)); +int i4bctlopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4bctlclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4bctlioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +#endif /* !FreeBSD */ + +#if BSD > 199306 && defined(__FreeBSD__) +/*---------------------------------------------------------------------------* + * initialization at kernel load time + *---------------------------------------------------------------------------*/ +static void +i4bctlinit(void *unused) +{ + dev_t dev; + + dev = makedev(CDEV_MAJOR, 0); + + cdevsw_add(&dev, &i4bctl_cdevsw, NULL); +} + +SYSINIT(i4bctldev, SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, &i4bctlinit, NULL); + +#endif /* BSD > 199306 && defined(__FreeBSD__) */ + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4bctlattach(void *dummy) +#else +i4bctlattach() +#endif +{ +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4bctl: ISDN system control port attached\n"); +#endif +#ifdef DEVFS + devfs_token = devfs_add_devswf(&i4bctl_cdevsw, 0, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4bctl", 0); +#endif +} + +/*---------------------------------------------------------------------------* + * i4bctlopen - device driver open routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bctlopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + if(minor(dev)) + return (ENXIO); + + if(openflag) + return (EBUSY); + + openflag = 1; + + return (0); +} + +/*---------------------------------------------------------------------------* + * i4bctlclose - device driver close routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bctlclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + openflag = 0; + return (0); +} + +/*---------------------------------------------------------------------------* + * i4bctlioctl - device driver ioctl routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003 +i4bctlioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +#else +i4bctlioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) +#endif +{ + ctl_debug_t *cdbg; + int error = 0; + +#ifndef DO_I4B_DEBUG + return(ENODEV); +#else + if(minor(dev)) + return(ENODEV); + + switch(cmd) + { + case I4B_CTL_GET_DEBUG: + cdbg = (ctl_debug_t *)data; + cdbg->l1 = i4b_l1_debug; + cdbg->l2 = i4b_l2_debug; + cdbg->l3 = i4b_l3_debug; + cdbg->l4 = i4b_l4_debug; + break; + + case I4B_CTL_SET_DEBUG: + cdbg = (ctl_debug_t *)data; + i4b_l1_debug = cdbg->l1; + i4b_l2_debug = cdbg->l2; + i4b_l3_debug = cdbg->l3; + i4b_l4_debug = cdbg->l4; + break; + + case I4B_CTL_GET_HSCXSTAT: + { + hscxstat_t *hst; + struct isic_softc *sc; + hst = (hscxstat_t *)data; + + if( hst->unit < 0 || + hst->unit > ISIC_MAXUNIT || + hst->chan < 0 || + hst->chan > 1 ) + { + error = EINVAL; + break; + } + +#ifndef __FreeBSD__ + sc = isic_find_sc(hst->unit); +#else + sc = &isic_sc[hst->unit]; +#endif + hst->vfr = sc->sc_chan[hst->chan].stat_VFR; + hst->rdo = sc->sc_chan[hst->chan].stat_RDO; + hst->crc = sc->sc_chan[hst->chan].stat_CRC; + hst->rab = sc->sc_chan[hst->chan].stat_RAB; + hst->xdu = sc->sc_chan[hst->chan].stat_XDU; + hst->rfo = sc->sc_chan[hst->chan].stat_RFO; + break; + } + + case I4B_CTL_CLR_HSCXSTAT: + { + hscxstat_t *hst; + struct isic_softc *sc; + hst = (hscxstat_t *)data; + + if( hst->unit < 0 || + hst->unit > ISIC_MAXUNIT || + hst->chan < 0 || + hst->chan > 1 ) + { + error = EINVAL; + break; + } + +#ifndef __FreeBSD__ + sc = isic_find_sc(hst->unit); +#else + sc = &isic_sc[hst->unit]; +#endif + + sc->sc_chan[hst->chan].stat_VFR = 0; + sc->sc_chan[hst->chan].stat_RDO = 0; + sc->sc_chan[hst->chan].stat_CRC = 0; + sc->sc_chan[hst->chan].stat_RAB = 0; + sc->sc_chan[hst->chan].stat_XDU = 0; + sc->sc_chan[hst->chan].stat_RFO = 0; + + break; + } + + default: + error = ENOTTY; + break; + } + return(error); +#endif DO_I4B_DEBUG +} + +/*---------------------------------------------------------------------------* + * i4bctlpoll - device driver poll routine + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +static int +i4bctlpoll (dev_t dev, int events, struct proc *p) +{ + return (ENODEV); +} +#endif + +#endif /* NI4BCTL > 0 */ diff --git a/sys/i4b/driver/i4b_ipr.c b/sys/i4b/driver/i4b_ipr.c new file mode 100644 index 0000000..df3977c --- /dev/null +++ b/sys/i4b/driver/i4b_ipr.c @@ -0,0 +1,1115 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ipr.c - isdn4bsd IP over raw HDLC ISDN network driver + * --------------------------------------------------------- + * + * $Id: i4b_ipr.c,v 1.42 1998/12/18 14:20:44 hm Exp $ + * + * last edit-date: [Fri Dec 18 11:50:47 1998] + * + *---------------------------------------------------------------------------* + * + * statistics counter usage (interface lifetime): + * ---------------------------------------------- + * sc->sc_if.if_ipackets # of received packets + * sc->sc_if.if_ierrors # of error packets not going to upper layers + * sc->sc_if.if_opackets # of transmitted packets + * sc->sc_if.if_oerrors # of error packets not being transmitted + * sc->sc_if.if_collisions # of invalid ip packets after VJ decompression + * sc->sc_if.if_ibytes # of bytes coming in from the line (before VJ) + * sc->sc_if.if_obytes # of bytes going out to the line (after VJ) + * sc->sc_if.if_imcasts (currently unused) + * sc->sc_if.if_omcasts # of frames sent out of the fastqueue + * sc->sc_if.if_iqdrops # of frames dropped on input because queue full + * sc->sc_if.if_noproto # of frames dropped on output because !AF_INET + * + * statistics counter usage (connection lifetime): + * ----------------------------------------------- + * sc->sc_iinb # of ISDN incoming bytes from HSCX + * sc->sc_ioutb # of ISDN outgoing bytes from HSCX + * sc->sc_inb # of incoming bytes after decompression + * sc->sc_outb # of outgoing bytes before compression + * + *---------------------------------------------------------------------------*/ + +#include "i4bipr.h" + +#if NI4BIPR > 0 + +#ifdef __FreeBSD__ +#include "opt_i4b.h" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/errno.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#include <sys/sockio.h> +#ifdef IPR_VJ +#include <sys/malloc.h> +#endif +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/protosw.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/netisr.h> +#include <net/route.h> + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> + +#ifdef IPR_VJ +#include <net/slcompress.h> +#define IPR_COMPRESS IFF_LINK0 /* compress TCP traffic */ +#define IPR_AUTOCOMP IFF_LINK1 /* auto-enable TCP compression */ + +/*--------------------------------------------------------------------------- + * NOTICE: using NO separate buffer relies on the assumption, that the HSCX + * IRQ handler _always_ allocates a single, continuous mbuf cluster large + * enough to hold the maximum MTU size if the ipr interface ! + * + * CAUTION: i have re-defined IPR_VJ_USEBUFFER because it makes problems + * with 2 i4b's back to back running cvs over ssh, cvs simply + * aborts because it gets bad data. Everything else (telnet/ftp?etc) + * functions fine. + *---------------------------------------------------------------------------*/ +#define IPR_VJ_USEBUFFER /* define to use an allocated separate buffer*/ + /* undef to uncompress in the mbuf itself */ +#endif /* IPR_VJ */ + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include <sys/time.h> +#include <net/bpf.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_debug.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_l3l4.h> + +#include <i4b/layer4/i4b_l4.h> + +#ifndef __FreeBSD__ +#include <machine/cpu.h> /* For softnet */ +#endif + +#ifdef __FreeBSD__ +#define IPR_FMT "ipr%d: " +#define IPR_ARG(sc) ((sc)->sc_if.if_unit) +#define PDEVSTATIC static +#else +#define IPR_FMT "%s: " +#define IPR_ARG(sc) ((sc)->sc_if.if_xname) +#define PDEVSTATIC /* not static */ +#endif + +#define I4BIPRMTU 1500 /* regular MTU */ +#define I4BIPRMAXMTU 2000 /* max MTU */ +#define I4BIPRMINMTU 500 /* min MTU */ + +#define I4BIPRMAXQLEN 50 /* max queue length */ + +#define I4BIPRACCT 1 /* enable accounting messages */ +#define I4BIPRACCTINTVL 2 /* accounting msg interval in secs */ +#define I4BIPRADJFRXP 1 /* adjust 1st rxd packet */ + +/* initialized by L4 */ + +static drvr_link_t ipr_drvr_linktab[NI4BIPR]; +static isdn_link_t *isdn_linktab[NI4BIPR]; + +struct ipr_softc { + struct ifnet sc_if; /* network-visible interface */ + int sc_state; /* state of the interface */ + +#ifndef __FreeBSD__ + int sc_unit; /* unit number for Net/OpenBSD */ +#endif + + call_desc_t *sc_cdp; /* ptr to call descriptor */ + int sc_updown; /* soft state of interface */ + struct ifqueue sc_fastq; /* interactive traffic */ + int sc_dialresp; /* dialresponse */ + int sc_lastdialresp;/* last dialresponse */ + +#if I4BIPRACCT + int sc_iinb; /* isdn driver # of inbytes */ + int sc_ioutb; /* isdn driver # of outbytes */ + int sc_inb; /* # of bytes rx'd */ + int sc_outb; /* # of bytes tx'd */ + int sc_linb; /* last # of bytes rx'd */ + int sc_loutb; /* last # of bytes tx'd */ + int sc_fn; /* flag, first null acct */ +#endif + +#ifdef I4BIPRADJFRXP + int sc_first_pkt; /* flag, first rxd packet */ +#endif + +#ifdef IPR_VJ + struct slcompress sc_compr; /* tcp compression data */ +#ifdef IPR_VJ_USEBUFFER + u_char *sc_cbuf; /* tcp decompression buffer */ +#endif +#endif + +} ipr_softc[NI4BIPR]; + +enum ipr_states { + ST_IDLE, /* initialized, ready, idle */ + ST_DIALING, /* dialling out to remote */ + ST_CONNECTED_W, /* connected to remote */ + ST_CONNECTED_A, /* connected to remote */ +}; + +#ifdef __FreeBSD__ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +# define IOCTL_CMD_T u_long +#else +# define IOCTL_CMD_T int +#endif +PDEVSTATIC void i4biprattach(void *); +PSEUDO_SET(i4biprattach, i4b_ipr); +static int i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data); +#else +PDEVSTATIC void i4biprattach __P((void)); +static int i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data); +#endif + +static void iprwatchdog(struct ifnet *ifp); +static void ipr_init_linktab(int unit); +static void ipr_tx_queue_empty(int unit); +static int i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, struct rtentry *rtp); +static void iprclearqueues(struct ipr_softc *sc); + +/*===========================================================================* + * DEVICE DRIVER ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * interface attach routine at kernel boot time + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4biprattach(void *dummy) +#else +i4biprattach() +#endif +{ + struct ipr_softc *sc = ipr_softc; + int i; + +#ifndef HACK_NO_PSEUDO_ATTACH_MSG +#ifdef IPR_VJ + printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached (VJ header compression)\n", NI4BIPR); +#else + printf("i4bipr: %d IP over raw HDLC ISDN device(s) attached\n", NI4BIPR); +#endif +#endif + + for(i=0; i < NI4BIPR; sc++, i++) + { + ipr_init_linktab(i); + + DBGL4(L4_DIALST, "i4biprattach", ("setting dial state to ST_IDLE\n")); + + sc->sc_state = ST_IDLE; + +#ifdef __FreeBSD__ + sc->sc_if.if_name = "ipr"; +#if __FreeBSD__ < 3 + sc->sc_if.if_next = NULL; +#endif + sc->sc_if.if_unit = i; +#else + sprintf(sc->sc_if.if_xname, "ipr%d", i); + sc->sc_if.if_softc = sc; + sc->sc_unit = i; +#endif + +#ifdef IPR_VJ + sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX | IPR_AUTOCOMP; +#else + sc->sc_if.if_flags = IFF_POINTOPOINT | IFF_SIMPLEX; +#endif + + sc->sc_if.if_mtu = I4BIPRMTU; + sc->sc_if.if_type = IFT_ISDNBASIC; + sc->sc_if.if_ioctl = i4biprioctl; + sc->sc_if.if_output = i4biproutput; + + sc->sc_if.if_snd.ifq_maxlen = I4BIPRMAXQLEN; + sc->sc_fastq.ifq_maxlen = I4BIPRMAXQLEN; + + sc->sc_if.if_ipackets = 0; + sc->sc_if.if_ierrors = 0; + sc->sc_if.if_opackets = 0; + sc->sc_if.if_oerrors = 0; + sc->sc_if.if_collisions = 0; + sc->sc_if.if_ibytes = 0; + sc->sc_if.if_obytes = 0; + sc->sc_if.if_imcasts = 0; + sc->sc_if.if_omcasts = 0; + sc->sc_if.if_iqdrops = 0; + sc->sc_if.if_noproto = 0; + +#if I4BIPRACCT + sc->sc_if.if_timer = 0; + sc->sc_if.if_watchdog = iprwatchdog; + sc->sc_iinb = 0; + sc->sc_ioutb = 0; + sc->sc_inb = 0; + sc->sc_outb = 0; + sc->sc_linb = 0; + sc->sc_loutb = 0; + sc->sc_fn = 1; +#endif + +#ifdef IPR_VJ +#ifdef __FreeBSD__ + sl_compress_init(&sc->sc_compr, -1); +#else + sl_compress_init(&sc->sc_compr); +#endif + +#ifdef IPR_VJ_USEBUFFER + if(!((sc->sc_cbuf = + (u_char *)malloc(I4BIPRMAXMTU+128, M_DEVBUF, M_WAITOK)))) + { + panic("if_ipr.c, ipr_attach: VJ malloc failed"); + } +#endif +#endif + + sc->sc_updown = SOFT_ENA; /* soft enabled */ + + sc->sc_dialresp = DSTAT_NONE; /* no response */ + sc->sc_lastdialresp = DSTAT_NONE; + + if_attach(&sc->sc_if); + +#if NBPFILTER > 0 +#ifdef __FreeBSD__ + bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int)); +#else + bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_NULL, sizeof(u_int)); +#endif +#endif + } +} + +/*---------------------------------------------------------------------------* + * output a packet to the ISDN B-channel + *---------------------------------------------------------------------------*/ +static int +i4biproutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst, + struct rtentry *rtp) +{ + struct ipr_softc *sc; + int unit; + int s; + struct ifqueue *ifq; + struct ip *ip; + + s = SPLI4B(); + +#ifdef __FreeBSD__ + unit = ifp->if_unit; + sc = &ipr_softc[unit]; +#else + sc = ifp->if_softc; + unit = sc->sc_unit; +#endif + + /* check for IP */ + + if(dst->sa_family != AF_INET) + { + printf(IPR_FMT "af%d not supported\n", IPR_ARG(sc), dst->sa_family); + m_freem(m); + splx(s); + sc->sc_if.if_noproto++; + sc->sc_if.if_oerrors++; + return(EAFNOSUPPORT); + } + + /* check interface state = UP */ + + if(!(ifp->if_flags & IFF_UP)) + { + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: interface is DOWN!\n", unit)); + m_freem(m); + splx(s); + sc->sc_if.if_oerrors++; + return(ENETDOWN); + } + + /* dial if necessary */ + + if(sc->sc_state == ST_IDLE || sc->sc_state == ST_DIALING) + { + +#ifdef NOTDEF + switch(sc->sc_dialresp) + { + case DSTAT_TFAIL: /* transient failure */ + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: transient dial failure!\n", unit)); + m_freem(m); + iprclearqueues(sc); + sc->sc_dialresp = DSTAT_NONE; + splx(s); + sc->sc_if.if_oerrors++; + return(ENETUNREACH); + break; + + case DSTAT_PFAIL: /* permanent failure */ + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: permanent dial failure!\n", unit)); + m_freem(m); + iprclearqueues(sc); + sc->sc_dialresp = DSTAT_NONE; + splx(s); + sc->sc_if.if_oerrors++; + return(EHOSTUNREACH); + break; + + case DSTAT_INONLY: /* no dialout allowed*/ + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: dialout not allowed failure!\n", unit)); + m_freem(m); + iprclearqueues(sc); + sc->sc_dialresp = DSTAT_NONE; + splx(s); + sc->sc_if.if_oerrors++; + return(EHOSTUNREACH); + break; + } +#endif + + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: send dial request message!\n", unit)); + DBGL4(L4_DIALST, "i4biproutput", ("ipr%d: setting dial state to ST_DIALING\n", unit)); + i4b_l4_dialout(BDRV_IPR, unit); + sc->sc_state = ST_DIALING; + } + + /* update access time */ + + microtime(&sc->sc_if.if_lastchange); + + /* + * check, if type of service indicates interactive, i.e. telnet, + * traffic. in case it is interactive, put it into the fast queue, + * else (i.e. ftp traffic) put it into the "normal" queue + */ + + ip = mtod(m, struct ip *); /* get ptr to ip header */ + + if(ip->ip_tos & IPTOS_LOWDELAY) + ifq = &sc->sc_fastq; + else + ifq = &sc->sc_if.if_snd; + + /* check for space in choosen send queue */ + + if(IF_QFULL(ifq)) + { + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: send queue full!\n", unit)); + IF_DROP(ifq); + m_freem(m); + splx(s); + sc->sc_if.if_oerrors++; + return(ENOBUFS); + } + + DBGL4(L4_IPRDBG, "i4biproutput", ("ipr%d: add packet to send queue!\n", unit)); + + IF_ENQUEUE(ifq, m); + + ipr_tx_queue_empty(unit); + + splx(s); + + return (0); +} + +/*---------------------------------------------------------------------------* + * process ioctl + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static int +i4biprioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data) +#else +static int +i4biprioctl(struct ifnet *ifp, u_long cmd, caddr_t data) +#endif +{ +#ifdef __FreeBSD__ + struct ipr_softc *sc = &ipr_softc[ifp->if_unit]; +#else + struct ipr_softc *sc = ifp->if_softc; +#endif + + struct ifreq *ifr = (struct ifreq *)data; + struct ifaddr *ifa = (struct ifaddr *)data; + int s; + int error = 0; + + s = SPLI4B(); + + switch (cmd) + { + case SIOCAIFADDR: /* add interface address */ + case SIOCSIFADDR: /* set interface address */ + case SIOCSIFDSTADDR: /* set interface destination address */ + if(ifa->ifa_addr->sa_family != AF_INET) + error = EAFNOSUPPORT; + else + sc->sc_if.if_flags |= IFF_UP; + microtime(&sc->sc_if.if_lastchange); + break; + + case SIOCSIFFLAGS: /* set interface flags */ + if(!(ifr->ifr_flags & IFF_UP)) + { + if(sc->sc_if.if_flags & IFF_RUNNING) + { + /* disconnect ISDN line */ +#ifdef __FreeBSD__ + i4b_l4_drvrdisc(BDRV_IPR, ifp->if_unit); +#else + i4b_l4_drvrdisc(BDRV_IPR, sc->sc_unit); +#endif + sc->sc_if.if_flags &= ~IFF_RUNNING; + } + + sc->sc_state = ST_IDLE; + + /* empty queues */ + + iprclearqueues(sc); + } + + if(ifr->ifr_flags & IFF_DEBUG) + { + /* enable debug messages */ + } + + microtime(&sc->sc_if.if_lastchange); + break; + +#if !defined(__OpenBSD__) + case SIOCSIFMTU: /* set interface MTU */ + if(ifr->ifr_mtu > I4BIPRMAXMTU) + error = EINVAL; + else if(ifr->ifr_mtu < I4BIPRMINMTU) + error = EINVAL; + else + { + ifp->if_mtu = ifr->ifr_mtu; + microtime(&sc->sc_if.if_lastchange); + } + break; +#endif /* __OPENBSD__ */ + +#if 0 + /* not needed for FreeBSD, done in sl_compress_init() (-hm) */ + + /* need to add an ioctl: set VJ max slot ID + * #define IPRIOCSMAXCID _IOW('I', XXX, int) + */ +#ifdef IPR_VJ + case IPRIOCSMAXCID: + { + struct proc *p = curproc; /* XXX */ + if((error = suser(p->p_ucred, &p->p_acflag)) != 0) + return (error); + sl_compress_setup(sc->sc_compr, *(int *)data); + } + break; +#endif +#endif + default: + error = EINVAL; + break; + } + + splx(s); + + return(error); +} + +/*---------------------------------------------------------------------------* + * clear the interface's send queues + *---------------------------------------------------------------------------*/ +static void +iprclearqueues(struct ipr_softc *sc) +{ + int x; + struct mbuf *m; + + for(;;) + { + x = splimp(); + IF_DEQUEUE(&sc->sc_fastq, m); + splx(x); + + if(m) + m_freem(m); + else + break; + } + + for(;;) + { + x = splimp(); + IF_DEQUEUE(&sc->sc_if.if_snd, m); + splx(x); + + if(m) + m_freem(m); + else + break; + } +} + +#if I4BIPRACCT +/*---------------------------------------------------------------------------* + * watchdog routine + *---------------------------------------------------------------------------*/ +static void +iprwatchdog(struct ifnet *ifp) +{ +#ifdef __FreeBSD__ + int unit = ifp->if_unit; + struct ipr_softc *sc = &ipr_softc[unit]; +#else + struct ipr_softc *sc = ifp->if_softc; + int unit = sc->sc_unit; +#endif + bchan_statistics_t bs; + + /* get # of bytes in and out from the HSCX driver */ + + (*isdn_linktab[unit]->bch_stat) + (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs); + + sc->sc_ioutb += bs.outbytes; + sc->sc_iinb += bs.inbytes; + + if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn) + { + int ri = (sc->sc_iinb - sc->sc_linb)/I4BIPRACCTINTVL; + int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BIPRACCTINTVL; + + if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb)) + sc->sc_fn = 0; + else + sc->sc_fn = 1; + + sc->sc_linb = sc->sc_iinb; + sc->sc_loutb = sc->sc_ioutb; + + i4b_l4_accounting(BDRV_IPR, unit, ACCT_DURING, + sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb); + } + sc->sc_if.if_timer = I4BIPRACCTINTVL; +} +#endif /* I4BIPRACCT */ + +/*===========================================================================* + * ISDN INTERFACE ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * start transmitting after connect + *---------------------------------------------------------------------------*/ +static void +i4bipr_connect_startio(int unit) +{ + struct ipr_softc *sc = &ipr_softc[unit]; + int s = SPLI4B(); + + if(sc->sc_state == ST_CONNECTED_W) + { + sc->sc_state = ST_CONNECTED_A; + ipr_tx_queue_empty(unit); + } + + splx(s); +} + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at connect time + *---------------------------------------------------------------------------*/ +static void +ipr_connect(int unit, void *cdp) +{ + struct ipr_softc *sc = &ipr_softc[unit]; + int s; + + sc->sc_cdp = (call_desc_t *)cdp; + + s = SPLI4B(); + + DBGL4(L4_DIALST, "ipr_connect", ("ipr%d: setting dial state to ST_CONNECTED\n", unit)); + + sc->sc_if.if_flags |= IFF_RUNNING; + sc->sc_state = ST_CONNECTED_W; + + sc->sc_dialresp = DSTAT_NONE; + sc->sc_lastdialresp = DSTAT_NONE; + +#if I4BIPRACCT + sc->sc_iinb = 0; + sc->sc_ioutb = 0; + sc->sc_inb = 0; + sc->sc_outb = 0; + sc->sc_linb = 0; + sc->sc_loutb = 0; + sc->sc_if.if_timer = I4BIPRACCTINTVL; +#endif + +#ifdef I4BIPRADJFRXP + sc->sc_first_pkt = 1; +#endif + + /* + * Sometimes ISDN B-channels are switched thru asymmetic. This + * means that under such circumstances B-channel data (the first + * three packets of a TCP connection in my case) may get lost, + * causing a large delay until the connection is started. + * When the sending of the very first packet of a TCP connection + * is delayed for a to be empirically determined delay (close + * to a second in my case) those packets go thru and the TCP + * connection comes up "almost" immediately (-hm). + */ + + if(sc->sc_cdp->isdntxdelay > 0) + { + timeout((TIMEOUT_FUNC_T)i4bipr_connect_startio, (void *)unit, sc->sc_cdp->isdntxdelay /* hz*1 */); + } + else + { + sc->sc_state = ST_CONNECTED_A; + ipr_tx_queue_empty(unit); + } + + splx(s); + + /* we don't need any negotiation - pass event back right now */ + i4b_l4_negcomplete(sc->sc_cdp); +} + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at disconnect time + *---------------------------------------------------------------------------*/ +static void +ipr_disconnect(int unit, void *cdp) +{ + call_desc_t *cd = (call_desc_t *)cdp; + struct ipr_softc *sc = &ipr_softc[unit]; + + /* new stuff to check that the active channel is being closed */ + + if (cd != sc->sc_cdp) + { + DBGL4(L4_IPRDBG, "ipr_disconnect", ("ipr%d: channel %d not active\n", + cd->driver_unit, cd->channelid)); + return; + } + +#if I4BIPRACCT + sc->sc_if.if_timer = 0; +#endif + + i4b_l4_accounting(BDRV_IPR, cd->driver_unit, ACCT_FINAL, + sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb); + + sc->sc_cdp = (call_desc_t *)0; + + DBGL4(L4_DIALST, "ipr_disconnect", ("setting dial state to ST_IDLE\n")); + + sc->sc_dialresp = DSTAT_NONE; + sc->sc_lastdialresp = DSTAT_NONE; + + sc->sc_if.if_flags &= ~IFF_RUNNING; + sc->sc_state = ST_IDLE; +} + +/*---------------------------------------------------------------------------* + * this routine is used to give a feedback from userland daemon + * in case of dial problems + *---------------------------------------------------------------------------*/ +static void +ipr_dialresponse(int unit, int status) +{ + struct ipr_softc *sc = &ipr_softc[unit]; + sc->sc_dialresp = status; + + DBGL4(L4_IPRDBG, "ipr_dialresponse", ("ipr%d: last=%d, this=%d\n", + unit, sc->sc_lastdialresp, sc->sc_dialresp)); +} + +/*---------------------------------------------------------------------------* + * interface soft up/down + *---------------------------------------------------------------------------*/ +static void +ipr_updown(int unit, int updown) +{ + struct ipr_softc *sc = &ipr_softc[unit]; + sc->sc_updown = updown; +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when a new frame (mbuf) has been received and was put on + * the rx queue. It is assumed that this routines runs at + * pri level splimp() ! Keep it short ! + *---------------------------------------------------------------------------*/ +static void +ipr_rx_data_rdy(int unit) +{ + register struct ipr_softc *sc = &ipr_softc[unit]; + register struct mbuf *m; +#ifdef IPR_VJ +#ifdef IPR_VJ_USEBUFFER + u_char *cp = sc->sc_cbuf; +#endif + int len, c; +#endif + + if((m = *isdn_linktab[unit]->rx_mbuf) == NULL) + return; + + m->m_pkthdr.rcvif = &sc->sc_if; + + m->m_pkthdr.len = m->m_len; + + microtime(&sc->sc_if.if_lastchange); + +#ifdef I4BIPRADJFRXP + + /* + * The very first packet after the B channel is switched thru + * has very often several bytes of random data prepended. This + * routine looks where the IP header starts and removes the + * the bad data. + */ + + if(sc->sc_first_pkt) + { + unsigned char *mp = m->m_data; + int i; + + sc->sc_first_pkt = 0; + + for(i = 0; i < m->m_len; i++, mp++) + { + if( ((*mp & 0xf0) == 0x40) && + ((*mp & 0x0f) >= 0x05) ) + { + m->m_data = mp; + m->m_pkthdr.len -= i; + break; + } + } + } +#endif + + sc->sc_if.if_ipackets++; + sc->sc_if.if_ibytes += m->m_pkthdr.len; + +#ifdef IPR_VJ + if((c = (*(mtod(m, u_char *)) & 0xf0)) != (IPVERSION << 4)) + { + /* copy data to buffer */ + + len = m->m_len; + +#ifdef IPR_VJ_USEBUFFER +/* XXX */ m_copydata(m, 0, len, cp); +#endif + + if(c & 0x80) + { + c = TYPE_COMPRESSED_TCP; + } + else if(c == TYPE_UNCOMPRESSED_TCP) + { +#ifdef IPR_VJ_USEBUFFER + *cp &= 0x4f; /* XXX */ +#else + *(mtod(m, u_char *)) &= 0x4f; +#endif + } + + /* + * We've got something that's not an IP packet. + * If compression is enabled, try to decompress it. + * Otherwise, if `auto-enable' compression is on and + * it's a reasonable packet, decompress it and then + * enable compression. Otherwise, drop it. + */ + if(sc->sc_if.if_flags & IPR_COMPRESS) + { +#ifdef IPR_VJ_USEBUFFER + len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr); +#else + len = sl_uncompress_tcp((u_char **)&m->m_data, len, + (u_int)c, &sc->sc_compr); +#endif + + if(len <= 0) + { +#ifdef DEBUG_IPR_VJ + printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_COMPRESS!\n"); +#endif + goto error; + } + } + else if((sc->sc_if.if_flags & IPR_AUTOCOMP) && + (c == TYPE_UNCOMPRESSED_TCP) && (len >= 40)) + { +#ifdef IPR_VJ_USEBUFFER + len = sl_uncompress_tcp(&cp,len,(u_int)c,&sc->sc_compr); +#else + len = sl_uncompress_tcp((u_char **)&m->m_data, len, + (u_int)c, &sc->sc_compr); +#endif + + if(len <= 0) + { +#ifdef DEBUG_IPR_VJ + printf("i4b_ipr, ipr_rx_data_rdy: len <= 0 IPR_AUTOCOMP!\n"); +#endif + goto error; + } + + sc->sc_if.if_flags |= IPR_COMPRESS; + } + else + { +#ifdef DEBUG_IPR_VJ + printf("i4b_ipr, ipr_input: invalid ip packet!\n"); +#endif + +error: + sc->sc_if.if_ierrors++; + sc->sc_if.if_collisions++; + m_freem(m); + return; + } +#ifdef IPR_VJ_USEBUFFER +/* XXX */ m_copyback(m, 0, len, cp); +#else + m->m_len = m->m_pkthdr.len = len; +#endif + } +#endif + +#if I4BIPRACCT + /* NB. do the accounting after decompression! */ + sc->sc_inb += m->m_pkthdr.len; +#endif + +#if NBPFILTER > 0 + if(sc->sc_if.if_bpf) + { + /* prepend the address family as a four byte field */ + struct mbuf mm; + u_int af = AF_INET; + mm.m_next = m; + mm.m_len = 4; + mm.m_data = (char *)⁡ + +#ifdef __FreeBSD__ + bpf_mtap(&sc->sc_if, &mm); +#else + bpf_mtap(sc->sc_if.if_bpf, &mm); +#endif + } +#endif /* NBPFILTER > 0 */ + + if(IF_QFULL(&ipintrq)) + { + DBGL4(L4_IPRDBG, "ipr_rx_data_rdy", ("ipr%d: ipintrq full!\n", unit)); + + IF_DROP(&ipintrq); + sc->sc_if.if_ierrors++; + sc->sc_if.if_iqdrops++; + m_freem(m); + } + else + { + IF_ENQUEUE(&ipintrq, m); + schednetisr(NETISR_IP); + } +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when the last frame has been sent out and there is no + * further frame (mbuf) in the tx queue. + *---------------------------------------------------------------------------*/ +static void +ipr_tx_queue_empty(int unit) +{ + register struct ipr_softc *sc = &ipr_softc[unit]; + register struct mbuf *m; +#ifdef IPR_VJ + struct ip *ip; +#endif + int x = 0; + + if(sc->sc_state != ST_CONNECTED_A) + return; + + for(;;) + { + IF_DEQUEUE(&sc->sc_fastq, m); + if(m) + { + sc->sc_if.if_omcasts++; + } + else + { + IF_DEQUEUE(&sc->sc_if.if_snd, m); + if(m == NULL) + break; + } + + microtime(&sc->sc_if.if_lastchange); + +#if NBPFILTER > 0 + if(sc->sc_if.if_bpf) + { + /* prepend the address family as a four byte field */ + + struct mbuf mm; + u_int af = AF_INET; + mm.m_next = m; + mm.m_len = 4; + mm.m_data = (char *)⁡ + +#ifdef __FreeBSD__ + bpf_mtap(&sc->sc_if, &mm); +#else + bpf_mtap(sc->sc_if.if_bpf, &mm); +#endif + } +#endif /* NBPFILTER */ + +#if I4BIPRACCT + sc->sc_outb += m->m_pkthdr.len; /* size before compression */ +#endif + +#ifdef IPR_VJ + if((ip = mtod(m, struct ip *))->ip_p == IPPROTO_TCP) + { + if(sc->sc_if.if_flags & IPR_COMPRESS) + { + *mtod(m, u_char *) |= sl_compress_tcp(m, ip, + &sc->sc_compr, 1); + } + } +#endif + x = 1; + + IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m); + + sc->sc_if.if_obytes += m->m_pkthdr.len; + + sc->sc_if.if_opackets++; + } + + if(x) + (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel); +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * each time a packet is received or transmitted. It should + * be used to implement an activity timeout mechanism. + *---------------------------------------------------------------------------*/ +static void +ipr_activity(int unit, int rxtx) +{ + ipr_softc[unit].sc_cdp->last_active_time = SECOND; +} + +/*---------------------------------------------------------------------------* + * return this drivers linktab address + *---------------------------------------------------------------------------*/ +drvr_link_t * +ipr_ret_linktab(int unit) +{ + return(&ipr_drvr_linktab[unit]); +} + +/*---------------------------------------------------------------------------* + * setup the isdn_linktab for this driver + *---------------------------------------------------------------------------*/ +void +ipr_set_linktab(int unit, isdn_link_t *ilt) +{ + isdn_linktab[unit] = ilt; +} + +/*---------------------------------------------------------------------------* + * initialize this drivers linktab + *---------------------------------------------------------------------------*/ +static void +ipr_init_linktab(int unit) +{ + ipr_drvr_linktab[unit].unit = unit; + ipr_drvr_linktab[unit].bch_rx_data_ready = ipr_rx_data_rdy; + ipr_drvr_linktab[unit].bch_tx_queue_empty = ipr_tx_queue_empty; + ipr_drvr_linktab[unit].bch_activity = ipr_activity; + ipr_drvr_linktab[unit].line_connected = ipr_connect; + ipr_drvr_linktab[unit].line_disconnected = ipr_disconnect; + ipr_drvr_linktab[unit].dial_response = ipr_dialresponse; + ipr_drvr_linktab[unit].updown_ind = ipr_updown; +} + +/*===========================================================================*/ + +#endif /* NI4BIPR > 0 */ diff --git a/sys/i4b/driver/i4b_isppp.c b/sys/i4b/driver/i4b_isppp.c new file mode 100644 index 0000000..b1cb2cf --- /dev/null +++ b/sys/i4b/driver/i4b_isppp.c @@ -0,0 +1,710 @@ +/* + * Copyright (c) 1997 Joerg Wunsch. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isppp.c - isdn4bsd kernel SyncPPP driver + * -------------------------------------------- + * + * Uses Serge Vakulenko's sppp backend (originally contributed with + * the "cx" driver for Cronyx's HDLC-in-hardware device). This driver + * is only the glue between sppp and i4b. + * + * $Id: i4b_isppp.c,v 1.20 1998/12/18 14:20:44 hm Exp $ + * + * last edit-date: [Fri Dec 18 11:47:58 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4bisppp.h" +#ifdef __FreeBSD__ +#include "sppp.h" +#endif + +#if NI4BISPPP == 0 +# error "You need to define `pseudo-device sppp <N>' with options ISPPP" +#endif + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <sys/errno.h> +#include <sys/ioccom.h> +#include <sys/sockio.h> +#include <sys/kernel.h> +#include <sys/protosw.h> + +#include <net/if.h> +#include <net/if_types.h> +#include <net/netisr.h> +#include <net/route.h> +#ifdef __FreeBSD__ +#include <net/if_sppp.h> +#else +#include <i4b/sppp/if_sppp.h> +#endif + +#include <netinet/in.h> +#include <netinet/in_systm.h> +#include <netinet/in_var.h> +#include <netinet/ip.h> + +#include "bpfilter.h" +#if NBPFILTER > 0 +#include <sys/time.h> +#include <net/bpf.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_l3l4.h> + +#include <i4b/layer4/i4b_l4.h> + +#ifdef __FreeBSD__ +#define ISPPP_FMT "isp%d: " +#define ISPPP_ARG(sc) ((sc)->sc_if.if_unit) +#define PDEVSTATIC static +#define IFP2UNIT(ifp) (ifp)->if_unit + +# if __FreeBSD_version >= 300001 +# define CALLOUT_INIT(chan) callout_handle_init(chan) +# define TIMEOUT(fun, arg, chan, tick) chan = timeout(fun, arg, tick) +# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg, chan) +# define IOCTL_CMD_T u_long +# else +# define CALLOUT_INIT(chan) do {} while(0) +# define TIMEOUT(fun, arg, chan, tick) timeout(fun, arg, tick) +# define UNTIMEOUT(fun, arg, chan) untimeout(fun, arg) +# define IOCTL_CMD_T int +# endif + +#elif defined __NetBSD__ || defined __OpenBSD__ +#define ISPPP_FMT "%s: " +#define ISPPP_ARG(sc) ((sc)->sc_if.if_xname) +#define PDEVSTATIC /* not static */ +#define IOCTL_CMD_T u_long +#define IFP2UNIT(ifp) ((struct i4bisppp_softc *)ifp->if_softc)->sc_unit +#else +# error "What system are you using?" +#endif + +#ifdef __FreeBSD__ +PDEVSTATIC void i4bispppattach(void *); +PSEUDO_SET(i4bispppattach, i4b_isppp); +#else +PDEVSTATIC void i4bispppattach __P((void)); +#endif + +#define I4BISPPPACCT 1 /* enable accounting messages */ +#define I4BISPPPACCTINTVL 2 /* accounting msg interval in secs */ +#define I4BISPPPDISCDEBUG 1 + +#define PPP_HDRLEN 4 /* 4 octetts PPP header length */ + +struct i4bisppp_softc { + /* + * struct sppp starts with a struct ifnet, but we gotta allocate + * more space for it. NB: do not relocate this union, it must + * be first in isppp_softc. The tls and tlf hooks below want to + * convert a ``struct sppp *'' into a ``struct isppp_softc *''. + */ + union { + struct ifnet scu_if; + struct sppp scu_sp; + } sc_if_un; +#define sc_if sc_if_un.scu_if + + int sc_state; /* state of the interface */ + +#ifndef __FreeBSD__ + int sc_unit; /* unit number for Net/OpenBSD */ +#endif + + call_desc_t *sc_cdp; /* ptr to call descriptor */ + +#ifdef I4BISPPPACCT + int sc_iinb; /* isdn driver # of inbytes */ + int sc_ioutb; /* isdn driver # of outbytes */ + int sc_inb; /* # of bytes rx'd */ + int sc_outb; /* # of bytes tx'd */ + int sc_linb; /* last # of bytes rx'd */ + int sc_loutb; /* last # of bytes tx'd */ + int sc_fn; /* flag, first null acct */ +#endif + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + struct callout_handle sc_ch; +#endif + +} i4bisppp_softc[NI4BISPPP]; + +static void i4bisppp_init_linktab(int unit); +static int i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data); + +#if 0 +static void i4bisppp_send(struct ifnet *ifp); +#endif + +static void i4bisppp_start(struct ifnet *ifp); + +#if 0 /* never used ??? */ +static void i4bisppp_timeout(void *cookie); +#endif + +static void i4bisppp_tls(struct sppp *sp); +static void i4bisppp_tlf(struct sppp *sp); +static void i4bisppp_state_changed(struct sppp *sp, int new_state); +static void i4bisppp_negotiation_complete(struct sppp *sp); +static void i4bisppp_watchdog(struct ifnet *ifp); + +/* initialized by L4 */ + +static drvr_link_t i4bisppp_drvr_linktab[NI4BISPPP]; +static isdn_link_t *isdn_linktab[NI4BISPPP]; + +enum i4bisppp_states { + ST_IDLE, /* initialized, ready, idle */ + ST_DIALING, /* dialling out to remote */ + ST_CONNECTED, /* connected to remote */ +}; + +/*===========================================================================* + * DEVICE DRIVER ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * interface attach routine at kernel boot time + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4bispppattach(void *dummy) +#else +i4bispppattach(void) +#endif +{ + struct i4bisppp_softc *sc = i4bisppp_softc; + int i; + +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4bisppp: %d ISDN SyncPPP device(s) attached\n", + NI4BISPPP); +#endif + + for(i = 0; i < NI4BISPPP; sc++, i++) { + i4bisppp_init_linktab(i); + + sc->sc_if.if_softc = sc; + +#ifdef __FreeBSD__ + sc->sc_if.if_name = "isp"; +#if defined(__FreeBSD_version) && __FreeBSD_version < 300001 + sc->sc_if.if_next = NULL; +#endif + sc->sc_if.if_unit = i; +#else + sprintf(sc->sc_if.if_xname, "isp%d", i); + sc->sc_unit = i; +#endif + + sc->sc_if.if_mtu = PP_MTU; + sc->sc_if.if_flags = IFF_SIMPLEX | IFF_POINTOPOINT; + sc->sc_if.if_type = IFT_ISDNBASIC; + sc->sc_state = ST_IDLE; + + sc->sc_if.if_ioctl = i4bisppp_ioctl; + + /* actually initialized by sppp_attach() */ + /* sc->sc_if.if_output = sppp_output; */ + + sc->sc_if.if_start = i4bisppp_start; + + sc->sc_if.if_hdrlen = 0; + sc->sc_if.if_addrlen = 0; + sc->sc_if.if_snd.ifq_maxlen = IFQ_MAXLEN; + + sc->sc_if.if_ipackets = 0; + sc->sc_if.if_ierrors = 0; + sc->sc_if.if_opackets = 0; + sc->sc_if.if_oerrors = 0; + sc->sc_if.if_collisions = 0; + sc->sc_if.if_ibytes = 0; + sc->sc_if.if_obytes = 0; + sc->sc_if.if_imcasts = 0; + sc->sc_if.if_omcasts = 0; + sc->sc_if.if_iqdrops = 0; + sc->sc_if.if_noproto = 0; + +#if I4BISPPPACCT + sc->sc_if.if_timer = 0; + sc->sc_if.if_watchdog = i4bisppp_watchdog; + sc->sc_iinb = 0; + sc->sc_ioutb = 0; + sc->sc_inb = 0; + sc->sc_outb = 0; + sc->sc_linb = 0; + sc->sc_loutb = 0; + sc->sc_fn = 1; +#endif + + sc->sc_if_un.scu_sp.pp_tls = i4bisppp_tls; + sc->sc_if_un.scu_sp.pp_tlf = i4bisppp_tlf; + sc->sc_if_un.scu_sp.pp_con = i4bisppp_negotiation_complete; + sc->sc_if_un.scu_sp.pp_chg = i4bisppp_state_changed; + + sppp_attach(&sc->sc_if); + if_attach(&sc->sc_if); + +#if NBPFILTER > 0 +#ifdef __FreeBSD__ + bpfattach(&sc->sc_if, DLT_PPP, PPP_HDRLEN); + CALLOUT_INIT(&sc->sc_ch); +#endif /* __FreeBSD__ */ +#ifdef __NetBSD__ + bpfattach(&sc->sc_if.if_bpf, &sc->sc_if, DLT_PPP, sizeof(u_int)); +#endif +#endif + } +} + +/*---------------------------------------------------------------------------* + * process ioctl + *---------------------------------------------------------------------------*/ +static int +i4bisppp_ioctl(struct ifnet *ifp, IOCTL_CMD_T cmd, caddr_t data) +{ + struct i4bisppp_softc *sc = ifp->if_softc; +#if 0 + struct sppp *sp = (struct sppp *)sc; + struct ifaddr *ifa = (struct ifaddr *) data; + struct ifreq *ifr = (struct ifreq *) data; +#endif + + int error; + + error = sppp_ioctl(&sc->sc_if, cmd, data); + if (error) + return error; + + switch(cmd) { + case SIOCSIFFLAGS: +#if 0 /* never used ??? */ + x = splimp(); + if ((ifp->if_flags & IFF_UP) == 0) + UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); + splx(x); +#endif + break; + } + + return 0; +} + +/*---------------------------------------------------------------------------* + * start output to ISDN B-channel + *---------------------------------------------------------------------------*/ +static void +i4bisppp_start(struct ifnet *ifp) +{ + struct i4bisppp_softc *sc = ifp->if_softc; + struct mbuf *m; + int s; + int unit = IFP2UNIT(ifp); + + if (sppp_isempty(ifp)) + return; + + if(sc->sc_state != ST_CONNECTED) + return; + + s = splimp(); + /*ifp->if_flags |= IFF_OACTIVE; - need to clear this somewhere */ + splx(s); + + while ((m = sppp_dequeue(&sc->sc_if)) != NULL) + { + +#if NBPFILTER > 0 +#ifdef __FreeBSD__ + if (ifp->if_bpf) + bpf_mtap(ifp, m); +#endif /* __FreeBSD__ */ + +#ifdef __NetBSD__ + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, m); +#endif +#endif /* NBPFILTER > 0 */ + + microtime(&ifp->if_lastchange); + + IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m); + + sc->sc_if.if_obytes += m->m_pkthdr.len; + sc->sc_outb += m->m_pkthdr.len; + sc->sc_if.if_opackets++; + } + isdn_linktab[unit]->bch_tx_start(isdn_linktab[unit]->unit, + isdn_linktab[unit]->channel); +} + +#ifdef I4BISPPPACCT +/*---------------------------------------------------------------------------* + * watchdog routine + *---------------------------------------------------------------------------*/ +static void +i4bisppp_watchdog(struct ifnet *ifp) +{ + struct i4bisppp_softc *sc = ifp->if_softc; + int unit = IFP2UNIT(ifp); + bchan_statistics_t bs; + + (*isdn_linktab[unit]->bch_stat) + (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs); + + sc->sc_ioutb += bs.outbytes; + sc->sc_iinb += bs.inbytes; + + if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn) + { + int ri = (sc->sc_iinb - sc->sc_linb)/I4BISPPPACCTINTVL; + int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BISPPPACCTINTVL; + + if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb)) + sc->sc_fn = 0; + else + sc->sc_fn = 1; + + sc->sc_linb = sc->sc_iinb; + sc->sc_loutb = sc->sc_ioutb; + + i4b_l4_accounting(BDRV_ISPPP, unit, ACCT_DURING, + sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_outb, sc->sc_inb); + } + sc->sc_if.if_timer = I4BISPPPACCTINTVL; + +#if 0 /* old stuff, keep it around */ + printf(ISPPP_FMT "transmit timeout\n", ISPPP_ARG(sc)); + i4bisppp_start(ifp); +#endif +} +#endif /* I4BISPPPACCT */ + +/* + *===========================================================================* + * SyncPPP layer interface routines + *===========================================================================* + */ + +#if 0 /* never used ??? */ +/*---------------------------------------------------------------------------* + * just an alias for i4bisppp_tls, but of type timeout_t + *---------------------------------------------------------------------------*/ +static void +i4bisppp_timeout(void *cookie) +{ + i4bisppp_tls((struct sppp *)cookie); +} +#endif + +/*---------------------------------------------------------------------------* + * PPP this-layer-started action + *---------------------------------------------------------------------------* + */ +static void +i4bisppp_tls(struct sppp *sp) +{ + struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp; + struct ifnet *ifp = (struct ifnet *)sp; + + if(sc->sc_state == ST_CONNECTED) + return; + + i4b_l4_dialout(BDRV_ISPPP, IFP2UNIT(ifp)); +} + +/*---------------------------------------------------------------------------* + * PPP this-layer-finished action + *---------------------------------------------------------------------------* + */ +static void +i4bisppp_tlf(struct sppp *sp) +{ + struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp; +/* call_desc_t *cd = sc->sc_cdp; */ + struct ifnet *ifp = (struct ifnet *)sp; + + if(sc->sc_state != ST_CONNECTED) + return; + +#if 0 /* never used ??? */ + UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); +#endif + + i4b_l4_drvrdisc(BDRV_ISPPP, IFP2UNIT(ifp)); +} +/*---------------------------------------------------------------------------* + * PPP interface phase change + *---------------------------------------------------------------------------* + */ +static void +i4bisppp_state_changed(struct sppp *sp, int new_state) +{ + struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp; + + i4b_l4_ifstate_changed(sc->sc_cdp, new_state); +} + +/*---------------------------------------------------------------------------* + * PPP control protocol negotiation complete (run ip-up script now) + *---------------------------------------------------------------------------* + */ +static void +i4bisppp_negotiation_complete(struct sppp *sp) +{ + struct i4bisppp_softc *sc = (struct i4bisppp_softc *)sp; + + i4b_l4_negcomplete(sc->sc_cdp); +} + +/*===========================================================================* + * ISDN INTERFACE ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at connect time + *---------------------------------------------------------------------------*/ +static void +i4bisppp_connect(int unit, void *cdp) +{ + struct i4bisppp_softc *sc = &i4bisppp_softc[unit]; + struct sppp *sp = &sc->sc_if_un.scu_sp; + int s = splimp(); + + sc->sc_cdp = (call_desc_t *)cdp; + sc->sc_state = ST_CONNECTED; + +#if I4BISPPPACCT + sc->sc_iinb = 0; + sc->sc_ioutb = 0; + sc->sc_inb = 0; + sc->sc_outb = 0; + sc->sc_linb = 0; + sc->sc_loutb = 0; + sc->sc_if.if_timer = I4BISPPPACCTINTVL; +#endif + +#if 0 /* never used ??? */ + UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); +#endif + + sp->pp_up(sp); /* tell PPP we are ready */ + + splx(s); +} + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at disconnect time + *---------------------------------------------------------------------------*/ +static void +i4bisppp_disconnect(int unit, void *cdp) +{ + call_desc_t *cd = (call_desc_t *)cdp; + struct i4bisppp_softc *sc = &i4bisppp_softc[unit]; + struct sppp *sp = &sc->sc_if_un.scu_sp; + + int s = splimp(); + + /* new stuff to check that the active channel is being closed */ + if (cd != sc->sc_cdp) + { +#ifdef I4BISPPPDISCDEBUG + printf("i4bisppp_disconnect: isppp%d channel%d not active\n", + cd->driver_unit, cd->channelid); +#endif + splx(s); + return; + } + +#if I4BISPPPACCT + sc->sc_if.if_timer = 0; +#endif + + i4b_l4_accounting(BDRV_ISPPP, unit, ACCT_FINAL, + sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb); + + if (sc->sc_state == ST_CONNECTED) + { +#if 0 /* never used ??? */ + UNTIMEOUT(i4bisppp_timeout, (void *)sp, sc->sc_ch); +#endif + sc->sc_cdp = (call_desc_t *)0; + /* do thhis here because pp_down calls i4bisppp_tlf */ + sc->sc_state = ST_IDLE; + sp->pp_down(sp); /* tell PPP we have hung up */ + } + + splx(s); +} + +/*---------------------------------------------------------------------------* + * this routine is used to give a feedback from userland demon + * in case of dial problems + *---------------------------------------------------------------------------*/ +static void +i4bisppp_dialresponse(int unit, int status) +{ +/* struct i4bisppp_softc *sc = &i4bisppp_softc[unit]; */ +} + +/*---------------------------------------------------------------------------* + * interface up/down + *---------------------------------------------------------------------------*/ +static void +i4bisppp_updown(int unit, int updown) +{ + /* could probably do something useful here */ +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when a new frame (mbuf) has been received and was put on + * the rx queue. + *---------------------------------------------------------------------------*/ +static void +i4bisppp_rx_data_rdy(int unit) +{ + struct i4bisppp_softc *sc = &i4bisppp_softc[unit]; + struct mbuf *m; + int s; + + if((m = *isdn_linktab[unit]->rx_mbuf) == NULL) + return; + + m->m_pkthdr.rcvif = &sc->sc_if; + m->m_pkthdr.len = m->m_len; + + microtime(&sc->sc_if.if_lastchange); + + sc->sc_if.if_ipackets++; + sc->sc_if.if_ibytes += m->m_pkthdr.len; + +#if I4BISPPPACCT + sc->sc_inb += m->m_pkthdr.len; +#endif + +#ifdef I4BISPPPDEBUG + printf("i4bisppp_rx_data_ready: received packet!\n"); +#endif + +#if NBPFILTER > 0 + +#ifdef __FreeBSD__ + if(sc->sc_if.if_bpf) + bpf_mtap(&sc->sc_if, m); +#endif /* __FreeBSD__ */ + +#ifdef __NetBSD__ + if(sc->sc_if.if_bpf) + bpf_mtap(sc->sc_if.if_bpf, m); +#endif + +#endif /* NBPFILTER > 0 */ + + s = splimp(); + + sppp_input(&sc->sc_if, m); + + splx(s); +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when the last frame has been sent out and there is no + * further frame (mbuf) in the tx queue. + *---------------------------------------------------------------------------*/ +static void +i4bisppp_tx_queue_empty(int unit) +{ + i4bisppp_start(&i4bisppp_softc[unit].sc_if); +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * each time a packet is received or transmitted. It should + * be used to implement an activity timeout mechanism. + *---------------------------------------------------------------------------*/ +static void +i4bisppp_activity(int unit, int rxtx) +{ + i4bisppp_softc[unit].sc_cdp->last_active_time = SECOND; +} + +/*---------------------------------------------------------------------------* + * return this drivers linktab address + *---------------------------------------------------------------------------*/ +drvr_link_t * +i4bisppp_ret_linktab(int unit) +{ + return(&i4bisppp_drvr_linktab[unit]); +} + +/*---------------------------------------------------------------------------* + * setup the isdn_linktab for this driver + *---------------------------------------------------------------------------*/ +void +i4bisppp_set_linktab(int unit, isdn_link_t *ilt) +{ + isdn_linktab[unit] = ilt; +} + +/*---------------------------------------------------------------------------* + * initialize this drivers linktab + *---------------------------------------------------------------------------*/ +static void +i4bisppp_init_linktab(int unit) +{ + i4bisppp_drvr_linktab[unit].unit = unit; + i4bisppp_drvr_linktab[unit].bch_rx_data_ready = i4bisppp_rx_data_rdy; + i4bisppp_drvr_linktab[unit].bch_tx_queue_empty = i4bisppp_tx_queue_empty; + i4bisppp_drvr_linktab[unit].bch_activity = i4bisppp_activity; + i4bisppp_drvr_linktab[unit].line_connected = i4bisppp_connect; + i4bisppp_drvr_linktab[unit].line_disconnected = i4bisppp_disconnect; + i4bisppp_drvr_linktab[unit].dial_response = i4bisppp_dialresponse; + i4bisppp_drvr_linktab[unit].updown_ind = i4bisppp_updown; +} + +/*===========================================================================*/ diff --git a/sys/i4b/driver/i4b_rbch.c b/sys/i4b/driver/i4b_rbch.c new file mode 100644 index 0000000..9cf432c --- /dev/null +++ b/sys/i4b/driver/i4b_rbch.c @@ -0,0 +1,820 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_rbch.c - device driver for raw B channel data + * --------------------------------------------------- + * + * $Id: i4b_rbch.c,v 1.23 1998/12/14 09:39:10 hm Exp $ + * + * last edit-date: [Sun Dec 13 10:19:08 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4brbch.h" + +#if NI4BRBCH > 0 + +#include <sys/param.h> +#include <sys/systm.h> + +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__) +#include <sys/ioccom.h> +#include <sys/poll.h> +#else +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#endif + +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) +#include <sys/filio.h> +#endif + +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/proc.h> +#include <sys/tty.h> + +#ifdef __NetBSD__ +extern cc_t ttydefchars; +#define termioschars(t) memcpy((t)->c_cc, &ttydefchars, sizeof((t)->c_cc)) +#endif + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __NetBSD__ +#include <sys/filio.h> +#define bootverbose 0 +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_debug.h> +#else +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_debug.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_l3l4.h> + +#include <i4b/layer4/i4b_l4.h> +/* initialized by L4 */ + +static drvr_link_t rbch_drvr_linktab[NI4BRBCH]; +static isdn_link_t *isdn_linktab[NI4BRBCH]; + +static struct rbch_softc { + int sc_devstate; /* state of driver */ +#define ST_IDLE 0x00 +#define ST_CONNECTED 0x01 +#define ST_ISOPEN 0x02 +#define ST_RDWAITDATA 0x04 +#define ST_WRWAITEMPTY 0x08 +#define ST_NOBLOCK 0x10 + + int sc_bprot; /* B-ch protocol used */ + + call_desc_t *cd; /* Call Descriptor */ + struct termios it_in; + + struct ifqueue sc_hdlcq; /* hdlc read queue */ +#define I4BRBCHMAXQLEN 10 + + struct selinfo selp; /* select / poll */ + +#ifdef DEVFS + void *devfs_token; /* device filesystem */ +#endif +} rbch_softc[NI4BRBCH]; + +static void rbch_rx_data_rdy(int unit); +static void rbch_tx_queue_empty(int unit); +static void rbch_connect(int unit, void *cdp); +static void rbch_disconnect(int unit, void *cdp); +static void rbch_init_linktab(int unit); +static void rbch_clrq(int unit); + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* - not static - */ +#define IOCTL_CMD_T u_long +void i4brbchattach __P((void)); +int i4brbchopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4brbchclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4brbchread __P((dev_t dev, struct uio *uio, int ioflag)); +int i4brbchwrite __P((dev_t dev, struct uio *uio, int ioflag)); +int i4brbchioctl __P((dev_t dev, IOCTL_CMD_T cmd, caddr_t arg, int flag, struct proc* pr)); +int i4brbchpoll __P((dev_t dev, int events, struct proc *p)); +#endif + +#if BSD > 199306 && defined(__FreeBSD__) +#define PDEVSTATIC static +#if !defined(__FreeBSD_version) || __FreeBSD_version < 300003 +#define IOCTL_CMD_T int +#else +#define IOCTL_CMD_T u_long +#endif + +PDEVSTATIC d_open_t i4brbchopen; +PDEVSTATIC d_close_t i4brbchclose; +PDEVSTATIC d_read_t i4brbchread; +PDEVSTATIC d_read_t i4brbchwrite; +PDEVSTATIC d_ioctl_t i4brbchioctl; + +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__) +PDEVSTATIC d_poll_t i4brbchpoll; +#else +PDEVSTATIC d_select_t i4brbchselect; +#endif + +#define CDEV_MAJOR 57 +static struct cdevsw i4brbch_cdevsw = { + i4brbchopen, i4brbchclose, i4brbchread, i4brbchwrite, + i4brbchioctl, nostop, noreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4brbchpoll, nommap, NULL, "i4brbch", NULL, -1 +#else + i4brbchselect, nommap, NULL, "i4brbch", NULL, -1 +#endif +}; + +static void i4brbchattach(void *); +PSEUDO_SET(i4brbchattach, i4b_rbch); + +/*===========================================================================* + * DEVICE DRIVER ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * initialization at kernel load time + *---------------------------------------------------------------------------*/ +static void +i4brbchinit(void *unused) +{ + dev_t dev; + + dev = makedev(CDEV_MAJOR, 0); + + cdevsw_add(&dev, &i4brbch_cdevsw, NULL); +} + +SYSINIT(i4brbchdev, SI_SUB_DRIVERS, + SI_ORDER_MIDDLE+CDEV_MAJOR, &i4brbchinit, NULL); + +#endif /* BSD > 199306 && defined(__FreeBSD__) */ + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4brbchattach(void *dummy) +#else +i4brbchattach() +#endif +{ + int i; + +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4brbch: %d raw B channel access device(s) attached\n", NI4BRBCH); +#endif + + for(i=0; i < NI4BRBCH; i++) + { +#ifdef DEVFS + rbch_softc[i].devfs_token = + devfs_add_devswf(&i4brbch_cdevsw, i, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4brbch%d", i); +#endif + rbch_softc[i].sc_devstate = ST_IDLE; + rbch_softc[i].sc_hdlcq.ifq_maxlen = I4BRBCHMAXQLEN; + rbch_softc[i].it_in.c_ispeed = rbch_softc[i].it_in.c_ospeed = 64000; + termioschars(&rbch_softc[i].it_in); + rbch_init_linktab(i); + } +} + +/*---------------------------------------------------------------------------* + * open rbch device + *---------------------------------------------------------------------------*/ +int +i4brbchopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit = minor(dev); + + if(unit > NI4BRBCH) + return(ENXIO); + + if(rbch_softc[unit].sc_devstate & ST_ISOPEN) + return(EBUSY); + + rbch_clrq(unit); + + rbch_softc[unit].sc_devstate |= ST_ISOPEN; + + DBGL4(L4_RBCHDBG, "i4brbchopen", ("unit %d, open\n", unit)); + + return(0); +} + +/*---------------------------------------------------------------------------* + * close rbch device + *---------------------------------------------------------------------------*/ +int +i4brbchclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit = minor(dev); + + if (rbch_softc[unit].cd) { + i4b_l4_disconnect_ind(rbch_softc[unit].cd); + rbch_softc[unit].cd = NULL; + } + rbch_softc[unit].sc_devstate &= ~ST_ISOPEN; + + rbch_clrq(unit); + + DBGL4(L4_RBCHDBG, "i4brbclose", ("unit %d, close\n", unit)); + + return(0); +} + +/*---------------------------------------------------------------------------* + * read from rbch device + *---------------------------------------------------------------------------*/ +int +i4brbchread(dev_t dev, struct uio *uio, int ioflag) +{ + struct mbuf *m; + int s; + int error = 0; + int unit = minor(dev); + struct ifqueue *iqp; + + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, enter read\n", unit)); + + if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, read while not open\n", unit)); + return(EIO); + } + + if((rbch_softc[unit].sc_devstate & ST_NOBLOCK)) { + if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED)) + return(EWOULDBLOCK); + + if(rbch_softc[unit].sc_bprot == BPROT_RHDLC) + iqp = &rbch_softc[unit].sc_hdlcq; + else + iqp = isdn_linktab[unit]->rx_queue; + + if(IF_QEMPTY(iqp) && (rbch_softc[unit].sc_devstate & ST_ISOPEN)) + return(EWOULDBLOCK); + } else { + while(!(rbch_softc[unit].sc_devstate & ST_CONNECTED)) + { + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, wait read init\n", unit)); + + if((error = tsleep((caddr_t) &rbch_softc[unit], + TTIPRI | PCATCH, + "rrrbch", 0 )) != 0) + { + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d tsleep\n", unit, error)); + return(error); + } + } + + if(rbch_softc[unit].sc_bprot == BPROT_RHDLC) + iqp = &rbch_softc[unit].sc_hdlcq; + else + iqp = isdn_linktab[unit]->rx_queue; + + while(IF_QEMPTY(iqp) && (rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + s = splimp(); + rbch_softc[unit].sc_devstate |= ST_RDWAITDATA; + splx(s); + + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, wait read data\n", unit)); + + if((error = tsleep((caddr_t) &isdn_linktab[unit]->rx_queue, + TTIPRI | PCATCH, + "rrbch", 0 )) != 0) + { + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d tsleep read\n", unit, error)); + rbch_softc[unit].sc_devstate &= ~ST_RDWAITDATA; + return(error); + } + } + } + + s = splimp(); + + IF_DEQUEUE(iqp, m); + + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, read %d bytes\n", unit, m->m_len)); + + if(m && m->m_len) + { + error = uiomove(m->m_data, m->m_len, uio); + } + else + { + DBGL4(L4_RBCHDBG, "i4brbchread", ("unit %d, error %d uiomove\n", unit, error)); + error = EIO; + } + + if(m) + i4b_Bfreembuf(m); + + splx(s); + + return(error); +} + +/*---------------------------------------------------------------------------* + * write to rbch device + *---------------------------------------------------------------------------*/ +int +i4brbchwrite(dev_t dev, struct uio * uio, int ioflag) +{ + struct mbuf *m; + int s; + int error = 0; + int unit = minor(dev); + + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write\n", unit)); + + if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write while not open\n", unit)); + return(EIO); + } + + if((rbch_softc[unit].sc_devstate & ST_NOBLOCK)) { + if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED)) + return(EWOULDBLOCK); + if(IF_QFULL(isdn_linktab[unit]->tx_queue) && (rbch_softc[unit].sc_devstate & ST_ISOPEN)) + return(EWOULDBLOCK); + } else { + while(!(rbch_softc[unit].sc_devstate & ST_CONNECTED)) + { + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write wait init\n", unit)); + + error = tsleep((caddr_t) &rbch_softc[unit], + TTIPRI | PCATCH, + "wrrbch", 0 ); + if(error == ERESTART) + return (ERESTART); + else if(error == EINTR) { + printf("\n ========= i4brbchwrite, EINTR during wait init ======== \n"); + return(EINTR); + } else if(error) { + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, error %d tsleep init\n", unit, error)); + return(error); + } +/*XXX*/ tsleep((caddr_t) &rbch_softc[unit], TTIPRI | PCATCH, "xrbch", (hz*1)); + } + + while(IF_QFULL(isdn_linktab[unit]->tx_queue) && (rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + s = splimp(); + rbch_softc[unit].sc_devstate |= ST_WRWAITEMPTY; + splx(s); + + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write queue full\n", unit)); + + if ((error = tsleep((caddr_t) &isdn_linktab[unit]->tx_queue, + TTIPRI | PCATCH, + "wrbch", 0)) != 0) { + rbch_softc[unit].sc_devstate &= ~ST_WRWAITEMPTY; + if(error == ERESTART) { + return(ERESTART); + } else if(error == EINTR) { + printf("\n ========= i4brbchwrite, EINTR during wait write ======== \n"); + return(error); + } else if(error) { + DBGL4(L4_RBCHDBG, "i4brbchwrite", + ("unit %d, error %d tsleep write\n", unit, error)); + return(error); + } + } + } + } + + s = splimp(); + + if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, not open anymore\n", unit)); + splx(s); + return(EIO); + } + + if((m = i4b_Bgetmbuf(BCH_MAX_DATALEN)) != NULL) + { + m->m_len = min(BCH_MAX_DATALEN, uio->uio_resid); + + DBGL4(L4_RBCHDBG, "i4brbchwrite", ("unit %d, write %d bytes\n", unit, m->m_len)); + + error = uiomove(m->m_data, m->m_len, uio); + + IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m); + + (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel); + } + + splx(s); + + return(error); +} + +PDEVSTATIC int +i4brbchioctl(dev_t dev, IOCTL_CMD_T cmd, caddr_t data, int flag, struct proc* p) { + int error = 0; + int unit = minor(dev); + + switch(cmd) + { +#if 0 + case I4B_RBCH_DIALOUT: +if(bootverbose)printf("EE-rbch%d: attempting dialout (ioctl)\n", unit); + i4b_l4_dialout(BDRV_RBCH, unit); + break; +#endif + + case FIOASYNC: /* Set async mode */ + if (*(int *)data) { +if(bootverbose)printf("EE-rbch%d: setting async mode\n", unit); + } else { +if(bootverbose)printf("EE-rbch%d: clearing async mode\n", unit); + } + break; + case FIONBIO: + if (*(int *)data) { +if(bootverbose)printf("EE-rbch%d: setting non-blocking mode\n", unit); + rbch_softc[unit].sc_devstate |= ST_NOBLOCK; + } else { +if(bootverbose)printf("EE-rbch%d: clearing non-blocking mode\n", unit); + rbch_softc[unit].sc_devstate &= ~ST_NOBLOCK; + } + break; + case TIOCCDTR: /* Clear DTR */ + if(rbch_softc[unit].sc_devstate & ST_CONNECTED) { +if(bootverbose)printf("EE-rbch%d: disconnecting for DTR down\n", unit); + i4b_l4_disconnect_ind(rbch_softc[unit].cd); + } + break; + case TIOCSDTR: /* Set DTR */ +if(bootverbose)printf("EE-rbch%d: attempting dialout (DTR)\n", unit); + i4b_l4_dialout(BDRV_RBCH, unit); + break; + case TIOCSETA: /* Set termios struct */ + break; + case TIOCGETA: /* Get termios struct */ + *(struct termios *)data = rbch_softc[unit].it_in; + break; + case TIOCMGET: + *(int *)data = TIOCM_LE|TIOCM_DTR|TIOCM_RTS|TIOCM_CTS|TIOCM_DSR; + if (rbch_softc[unit].sc_devstate & ST_CONNECTED) + *(int *)data |= TIOCM_CD; + break; + default: /* Unknown stuff */ + printf("\n ========= i4brbch%d - ioctl, unknown cmd %lx ==================== \n", + unit, + (u_long)cmd); + error = EINVAL; + break; + } + return(error); +} + +/*---------------------------------------------------------------------------* + * device driver poll + *---------------------------------------------------------------------------*/ +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || !defined(__FreeBSD__) + +PDEVSTATIC int +i4brbchpoll(dev_t dev, int events, struct proc *p) +{ + int revents = 0; /* Events we found */ + int s; + int unit = minor(dev); + + /* We can't check for anything but IN or OUT */ + + if((events & (POLLIN|POLLOUT)) == 0) + return(POLLNVAL); + + s = splhigh(); + + if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + splx(s); + return(POLLNVAL); + } + + /* + * Writes are OK if we are connected and the + * transmit queue can take them + */ + + if((events & POLLOUT) && + (rbch_softc[unit].sc_devstate & ST_CONNECTED) && + !IF_QFULL(isdn_linktab[unit]->tx_queue)) + { + revents |= POLLOUT; + } + + /* ... while reads are OK if we have any data */ + + if((events & POLLIN) && + (rbch_softc[unit].sc_devstate & ST_CONNECTED)) + { + struct ifqueue *iqp; + + if(rbch_softc[unit].sc_bprot == BPROT_RHDLC) + iqp = &rbch_softc[unit].sc_hdlcq; + else + iqp = isdn_linktab[unit]->rx_queue; + + if(!IF_QEMPTY(iqp)) + revents |= POLLIN; + } + + if(revents == 0) + selrecord(p, &rbch_softc[unit].selp); + + splx(s); + return(revents); +} + +#else + +/*---------------------------------------------------------------------------* + * device driver select + *---------------------------------------------------------------------------*/ +static int +i4brbchselect(dev_t dev, int rw, struct proc *p) +{ + int unit = minor(dev); + int s; + + s = splhigh(); + + if(!(rbch_softc[unit].sc_devstate & ST_ISOPEN)) + { + splx(s); + DBGL4(L4_RBCHDBG, "i4brbchselect", ("unit %d, not open anymore\n", unit)); + return(1); + } + + if(rbch_softc[unit].sc_devstate & ST_CONNECTED) + { + struct ifqueue *iqp; + + switch(rw) + { + case FREAD: + if(rbch_softc[unit].sc_bprot == BPROT_RHDLC) + iqp = &rbch_softc[unit].sc_hdlcq; + else + iqp = isdn_linktab[unit]->rx_queue; + + if(!IF_QEMPTY(iqp)) + return(1); + break; + + case FWRITE: + if(!IF_QFULL(isdn_linktab[unit]->rx_queue)) + return(1); + break; + + default: + return 0; + } + } + selrecord(p, &rbch_softc[unit].selp); + return(0); +} + +#endif /* defined(__FreeBSD_version) && __FreeBSD_version >= 300001 */ + +/*===========================================================================* + * ISDN INTERFACE ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at connect time + *---------------------------------------------------------------------------*/ +static void +rbch_connect(int unit, void *cdp) +{ + call_desc_t *cd = (call_desc_t *)cdp; + + rbch_softc[unit].sc_bprot = cd->bprot; + + if(!(rbch_softc[unit].sc_devstate & ST_CONNECTED)) + { + DBGL4(L4_RBCHDBG, "rbch_connect", ("unit %d, wakeup\n", unit)); + rbch_softc[unit].sc_devstate |= ST_CONNECTED; + rbch_softc[unit].cd = cdp; + wakeup((caddr_t) &rbch_softc[unit]); + } +} + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at disconnect time + *---------------------------------------------------------------------------*/ +static void +rbch_disconnect(int unit, void *cdp) +{ + /* call_desc_t *cd = (call_desc_t *)cdp; */ + + DBGL4(L4_RBCHDBG, "rbch_disconnect", ("unit %d, deinit\n", unit)); + rbch_softc[unit].sc_devstate &= ~ST_CONNECTED; + rbch_softc[unit].cd = NULL; +} + +/*---------------------------------------------------------------------------* + * feedback from daemon in case of dial problems + *---------------------------------------------------------------------------*/ +static void +rbch_dialresponse(int unit, int status) +{ +} + +/*---------------------------------------------------------------------------* + * interface up/down + *---------------------------------------------------------------------------*/ +static void +rbch_updown(int unit, int updown) +{ +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when a new frame (mbuf) has been received and is to be put on + * the rx queue. + *---------------------------------------------------------------------------*/ +static void +rbch_rx_data_rdy(int unit) +{ + if(rbch_softc[unit].sc_bprot == BPROT_RHDLC) + { + register struct mbuf *m; + + if((m = *isdn_linktab[unit]->rx_mbuf) == NULL) + return; + + m->m_pkthdr.len = m->m_len; + + if(IF_QFULL(&(rbch_softc[unit].sc_hdlcq))) + { + DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d: hdlc rx queue full!\n", unit)); + m_freem(m); + } + else + { + IF_ENQUEUE(&(rbch_softc[unit].sc_hdlcq), m); + } + } + + if(rbch_softc[unit].sc_devstate & ST_RDWAITDATA) + { + DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d, wakeup\n", unit)); + rbch_softc[unit].sc_devstate &= ~ST_RDWAITDATA; + wakeup((caddr_t) &isdn_linktab[unit]->rx_queue); + } + else + { + DBGL4(L4_RBCHDBG, "rbch_rx_data_rdy", ("unit %d, NO wakeup\n", unit)); + } + selwakeup(&rbch_softc[unit].selp); +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when the last frame has been sent out and there is no + * further frame (mbuf) in the tx queue. + *---------------------------------------------------------------------------*/ +static void +rbch_tx_queue_empty(int unit) +{ + if(rbch_softc[unit].sc_devstate & ST_WRWAITEMPTY) + { + DBGL4(L4_RBCHDBG, "rbch_tx_queue_empty", ("unit %d, wakeup\n", unit)); + rbch_softc[unit].sc_devstate &= ~ST_WRWAITEMPTY; + wakeup((caddr_t) &isdn_linktab[unit]->tx_queue); + } + else + { + DBGL4(L4_RBCHDBG, "rbch_tx_queue_empty", ("unit %d, NO wakeup\n", unit)); + } + selwakeup(&rbch_softc[unit].selp); +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * each time a packet is received or transmitted + *---------------------------------------------------------------------------*/ +static void +rbch_activity(int unit, int rxtx) +{ + if (rbch_softc[unit].cd) + rbch_softc[unit].cd->last_active_time = SECOND; + selwakeup(&rbch_softc[unit].selp); +} + +/*---------------------------------------------------------------------------* + * clear an hdlc rx queue for a rbch unit + *---------------------------------------------------------------------------*/ +static void +rbch_clrq(int unit) +{ + int x; + struct mbuf *m; + + for(;;) + { + x = splimp(); + IF_DEQUEUE(&rbch_softc[unit].sc_hdlcq, m); + splx(x); + if(m) + m_freem(m); + else + break; + } +} + +/*---------------------------------------------------------------------------* + * return this drivers linktab address + *---------------------------------------------------------------------------*/ +drvr_link_t * +rbch_ret_linktab(int unit) +{ + rbch_init_linktab(unit); + return(&rbch_drvr_linktab[unit]); +} + +/*---------------------------------------------------------------------------* + * setup the isdn_linktab for this driver + *---------------------------------------------------------------------------*/ +void +rbch_set_linktab(int unit, isdn_link_t *ilt) +{ + isdn_linktab[unit] = ilt; +} + +/*---------------------------------------------------------------------------* + * initialize this drivers linktab + *---------------------------------------------------------------------------*/ +static void +rbch_init_linktab(int unit) +{ + rbch_drvr_linktab[unit].unit = unit; + rbch_drvr_linktab[unit].bch_rx_data_ready = rbch_rx_data_rdy; + rbch_drvr_linktab[unit].bch_tx_queue_empty = rbch_tx_queue_empty; + rbch_drvr_linktab[unit].bch_activity = rbch_activity; + rbch_drvr_linktab[unit].line_connected = rbch_connect; + rbch_drvr_linktab[unit].line_disconnected = rbch_disconnect; + rbch_drvr_linktab[unit].dial_response = rbch_dialresponse; + rbch_drvr_linktab[unit].updown_ind = rbch_updown; +} + +/*===========================================================================*/ + +#endif /* NI4BRBCH > 0 */ diff --git a/sys/i4b/driver/i4b_tel.c b/sys/i4b/driver/i4b_tel.c new file mode 100644 index 0000000..81b38a6 --- /dev/null +++ b/sys/i4b/driver/i4b_tel.c @@ -0,0 +1,713 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tel.c - device driver for ISDN telephony + * -------------------------------------------- + * + * $Id: i4b_tel.c,v 1.18 1998/12/14 10:31:53 hm Exp $ + * + * last edit-date: [Mon Dec 14 11:32:06 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4btel.h" + +#if NI4BTEL > 0 + +#undef I4BTELDEBUG + +#include <sys/param.h> +#include <sys/systm.h> + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/proc.h> +#include <sys/tty.h> + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_tel_ioctl.h> +#else +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_tel_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_l3l4.h> + +typedef struct { + drvr_link_t drvr_linktab; /* driver linktab */ + isdn_link_t *isdn_linktab; /* isdn linktab */ + int devstate; /* state of this unit */ +#define ST_IDLE 0x00 /* idle */ +#define ST_CONNECTED 0x01 /* isdn connected state */ +#define ST_ISOPEN 0x02 /* userland opened */ +#define ST_RDWAITDATA 0x04 /* userland read waiting */ +#define ST_WRWAITEMPTY 0x08 /* userland write waiting */ + int audiofmt; /* audio format conversion */ + call_desc_t *cdp; /* call descriptor pointer */ +#ifdef DEVFS + void *devfs_token; /* token for DEVFS */ +#endif +} tel_sc_t; + +static tel_sc_t tel_sc[NI4BTEL]; + +/* forward decl */ + +static void tel_rx_data_rdy(int unit); +static void tel_tx_queue_empty(int unit); +static void tel_init_linktab(int unit); +static void tel_connect(int unit, void *cdp); +static void tel_disconnect(int unit, void *cdp); + +static unsigned char alaw_ulaw[]; +static unsigned char ulaw_alaw[]; + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* - not static - */ +PDEVSTATIC void i4btelattach __P((void)); +PDEVSTATIC int i4btelioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +int i4btelopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4btelclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4btelread __P((dev_t dev, struct uio *uio, int ioflag)); +int i4btelwrite __P((dev_t dev, struct uio * uio, int ioflag)); +#endif +#if BSD > 199306 && defined(__FreeBSD__) +#define PDEVSTATIC static +PDEVSTATIC d_open_t i4btelopen; +PDEVSTATIC d_close_t i4btelclose; +PDEVSTATIC d_read_t i4btelread; +PDEVSTATIC d_read_t i4btelwrite; +PDEVSTATIC d_ioctl_t i4btelioctl; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +PDEVSTATIC d_poll_t i4btelpoll; +#endif + +#define CDEV_MAJOR 56 +static struct cdevsw i4btel_cdevsw = { + i4btelopen, i4btelclose, i4btelread, i4btelwrite, + i4btelioctl, nostop, noreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4btelpoll, nommap, NULL, "i4btel", NULL, -1 +#else + noselect, nommap, NULL, "i4btel", NULL, -1 +#endif +}; + +PDEVSTATIC void i4btelinit(void *unused); + +PDEVSTATIC void i4btelattach(void *); +PSEUDO_SET(i4btelattach, i4b_tel); + +/*===========================================================================* + * DEVICE DRIVER ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * initialization at kernel load time + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +i4btelinit(void *unused) +{ + dev_t dev; + + dev = makedev(CDEV_MAJOR, 0); + + cdevsw_add(&dev, &i4btel_cdevsw, NULL); +} + +SYSINIT(i4bteldev, SI_SUB_DRIVERS, + SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btelinit, NULL); + +#endif /* BSD > 199306 && defined(__FreeBSD__) */ + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4btelattach(void *dummy) +#else +i4btelattach() +#endif +{ + int i; + +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4btel: %d ISDN telephony interface device(s) attached\n", NI4BTEL); +#endif + + for(i=0; i < NI4BTEL; i++) + { + tel_sc[i].devstate = ST_IDLE; + tel_sc[i].audiofmt = CVT_NONE; + tel_init_linktab(i); +#ifdef DEVFS + tel_sc[i].devfs_token + = devfs_add_devswf(&i4btel_cdevsw, i, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4btel%d", i); +#endif + } +} + +/*---------------------------------------------------------------------------* + * open tel device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btelopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit = minor(dev); + tel_sc_t *sc; + + if(unit > NI4BTEL) + return(ENXIO); + + sc = &tel_sc[unit]; + + if(!(sc->devstate & ST_CONNECTED)) + return(EIO); + + if(sc->devstate & ST_ISOPEN) + return(EBUSY); + + sc->devstate |= ST_ISOPEN; + + return(0); +} + +/*---------------------------------------------------------------------------* + * close tel device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btelclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit = minor(dev); + tel_sc_t *sc; + int error = 0; + + if(unit > NI4BTEL) + return(ENXIO); + + sc = &tel_sc[unit]; + + if(sc->isdn_linktab != NULL && sc->isdn_linktab->tx_queue != NULL) + { + while(!(IF_QEMPTY(sc->isdn_linktab->tx_queue))) + { + sc->devstate |= ST_WRWAITEMPTY; + + if((error = tsleep((caddr_t) &sc->isdn_linktab->tx_queue, + TTIPRI | PCATCH, "wtcl", 0)) != 0) + { + break; + } + } + sc->devstate &= ~ST_WRWAITEMPTY; + } + sc->devstate &= ~ST_ISOPEN; + return(error); +} + +/*---------------------------------------------------------------------------* + * i4btelioctl - device driver ioctl routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003 +i4btelioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +#else +i4btelioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) +#endif +{ + int error = 0; + struct mbuf *m; + int s; + tel_sc_t *sc = &tel_sc[minor(dev)]; + + switch(cmd) + { + case I4B_TEL_GETAUDIOFMT: + *(int *)data = sc->audiofmt; + break; + + case I4B_TEL_SETAUDIOFMT: + sc->audiofmt = *(int *)data; + break; + + case I4B_TEL_EMPTYINPUTQUEUE: + s = splimp(); + while((sc->devstate & ST_CONNECTED) && + (sc->devstate & ST_ISOPEN) && + !IF_QEMPTY(sc->isdn_linktab->rx_queue)) + { + IF_DEQUEUE(sc->isdn_linktab->rx_queue, m); + if(m) + i4b_Bfreembuf(m); + } + splx(s); + break; + + default: + error = ENOTTY; + break; + } + return(error); +} + +/*---------------------------------------------------------------------------* + * read from tel device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btelread(dev_t dev, struct uio *uio, int ioflag) +{ + struct mbuf *m; + int s; + int error = 0; + tel_sc_t *sc = &tel_sc[minor(dev)]; + + if(!(sc->devstate & ST_CONNECTED)) + return(EIO); + + if(!(sc->devstate & ST_ISOPEN)) + return(EIO); + +#ifdef NOTDEF + while(!(sc->devstate & ST_CONNECTED)) + { + if((error = tsleep((caddr_t) &sc->devstate, + TTIPRI | PCATCH, + "rrtel", 0 )) != 0) + { + return(error); + } + } +#endif + + while(IF_QEMPTY(sc->isdn_linktab->rx_queue) && + (sc->devstate & ST_ISOPEN) && + (sc->devstate & ST_CONNECTED)) + { + sc->devstate |= ST_RDWAITDATA; + + if((error = tsleep((caddr_t) &sc->isdn_linktab->rx_queue, + TTIPRI | PCATCH, + "rtel", 0 )) != 0) + { + sc->devstate &= ~ST_RDWAITDATA; + return(error); + } + } + + if(!(sc->devstate & ST_ISOPEN)) + { + return(EIO); + } + + if(!(sc->devstate & ST_CONNECTED)) + { + return(EIO); + } + + s = splimp(); + + IF_DEQUEUE(sc->isdn_linktab->rx_queue, m); + + if(m && m->m_len) + { + if(sc->audiofmt == CVT_ALAW2ULAW) + { + int i; + for(i = 0; i < m->m_len; i++) + m->m_data[i] = alaw_ulaw[(int)m->m_data[i]]; + } + error = uiomove(m->m_data, m->m_len, uio); + } + else + { + error = EIO; + } + + if(m) + i4b_Bfreembuf(m); + + splx(s); + + return(error); +} + +/*---------------------------------------------------------------------------* + * write to tel device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btelwrite(dev_t dev, struct uio * uio, int ioflag) +{ + struct mbuf *m; + int s; + int error = 0; + tel_sc_t *sc = &tel_sc[minor(dev)]; + + if(!(sc->devstate & ST_CONNECTED)) + return(EIO); + + if(!(sc->devstate & ST_ISOPEN)) + { + return(EIO); + } + +#ifdef NOTDEF + while(!(sc->devstate & ST_CONNECTED)) + { + if((error = tsleep((caddr_t) &sc->devstate, + TTIPRI | PCATCH, + "wrtel", 0 )) != 0) + { + return(error); + } + + /* + * XXX the originations B channel gets much earlier + * switched thru than the destinations B channel, so + * if the origination starts to send at once, some + * 200 bytes (at my site) or so get lost, so i delay + * a bit before sending. (-hm) + */ + + tsleep((caddr_t) &sc->devstate, TTIPRI | PCATCH, "xtel", (hz*1)); + } +#endif + + while((IF_QFULL(sc->isdn_linktab->tx_queue)) && + (sc->devstate & ST_ISOPEN)) + { + sc->devstate |= ST_WRWAITEMPTY; + + if((error = tsleep((caddr_t) &sc->isdn_linktab->tx_queue, + TTIPRI | PCATCH, "wtel", 0)) != 0) + { + sc->devstate &= ~ST_WRWAITEMPTY; + return(error); + } + } + + if(!(sc->devstate & ST_ISOPEN)) + { + return(EIO); + } + + if(!(sc->devstate & ST_CONNECTED)) + { + return(EIO); + } + + s = splimp(); + + if((m = i4b_Bgetmbuf(BCH_MAX_DATALEN)) != NULL) + { + m->m_len = min(BCH_MAX_DATALEN, uio->uio_resid); + + error = uiomove(m->m_data, m->m_len, uio); + + if(sc->audiofmt == CVT_ALAW2ULAW) + { + int i; + for(i = 0; i < m->m_len; i++) + m->m_data[i] = ulaw_alaw[(int)m->m_data[i]]; + } + + IF_ENQUEUE(sc->isdn_linktab->tx_queue, m); + + (*sc->isdn_linktab->bch_tx_start)(sc->isdn_linktab->unit, sc->isdn_linktab->channel); + } + + splx(s); + + return(error); +} + +/*---------------------------------------------------------------------------* + * poll + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +PDEVSTATIC int +i4btelpoll (dev_t dev, int events, struct proc *p) +{ + return (ENODEV); +} +#endif + +/*===========================================================================* + * ISDN INTERFACE ROUTINES + *===========================================================================*/ + +/*---------------------------------------------------------------------------* +* this routine is called from L4 handler at connect time + *---------------------------------------------------------------------------*/ +static void +tel_connect(int unit, void *cdp) +{ + tel_sc_t *sc = &tel_sc[unit]; + + sc->cdp = (call_desc_t *)cdp; + +#ifdef NOTDEF + if(!(sc->devstate & ST_CONNECTED)) + { + sc->devstate |= ST_CONNECTED; + wakeup((caddr_t) &sc->devstate); + } +#else + sc->devstate |= ST_CONNECTED; +#endif +} + +/*---------------------------------------------------------------------------* + * this routine is called from L4 handler at disconnect time + *---------------------------------------------------------------------------*/ +static void +tel_disconnect(int unit, void *cdp) +{ +/* call_desc_t *cd = (call_desc_t *)cdp; */ + + tel_sc_t *sc = &tel_sc[unit]; + + sc->devstate &= ~ST_CONNECTED; + + if(sc->devstate & ST_RDWAITDATA) + { + sc->devstate &= ~ST_RDWAITDATA; + wakeup((caddr_t) &sc->isdn_linktab->rx_queue); + } + + if(sc->devstate & ST_WRWAITEMPTY) + { + sc->devstate &= ~ST_WRWAITEMPTY; + wakeup((caddr_t) &sc->isdn_linktab->tx_queue); + } +} + +/*---------------------------------------------------------------------------* + * feedback from daemon in case of dial problems + *---------------------------------------------------------------------------*/ +static void +tel_dialresponse(int unit, int status) +{ +} + +/*---------------------------------------------------------------------------* + * interface up/down + *---------------------------------------------------------------------------*/ +static void +tel_updown(int unit, int updown) +{ +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when a new frame (mbuf) has been received and was put on + * the rx queue. + *---------------------------------------------------------------------------*/ +static void +tel_rx_data_rdy(int unit) +{ + tel_sc_t *sc = &tel_sc[unit]; + + if(sc->devstate & ST_RDWAITDATA) + { + sc->devstate &= ~ST_RDWAITDATA; + wakeup((caddr_t) &sc->isdn_linktab->rx_queue); + } +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * when the last frame has been sent out and there is no + * further frame (mbuf) in the tx queue. + *---------------------------------------------------------------------------*/ +static void +tel_tx_queue_empty(int unit) +{ + tel_sc_t *sc = &tel_sc[unit]; + + if(sc->devstate & ST_WRWAITEMPTY) + { + sc->devstate &= ~ST_WRWAITEMPTY; + wakeup((caddr_t) &sc->isdn_linktab->tx_queue); + } +} + +/*---------------------------------------------------------------------------* + * this routine is called from the HSCX interrupt handler + * each time a packet is received or transmitted. + *---------------------------------------------------------------------------*/ +static void +tel_activity(int unit, int rxtx) +{ + tel_sc[unit].cdp->last_active_time = SECOND; +} + +/*---------------------------------------------------------------------------* + * return this drivers linktab address + *---------------------------------------------------------------------------*/ +drvr_link_t * +tel_ret_linktab(int unit) +{ + tel_sc_t *sc = &tel_sc[unit]; + + tel_init_linktab(unit); + return(&sc->drvr_linktab); +} + +/*---------------------------------------------------------------------------* + * setup the isdn_linktab for this driver + *---------------------------------------------------------------------------*/ +void +tel_set_linktab(int unit, isdn_link_t *ilt) +{ + tel_sc_t *sc = &tel_sc[unit]; + sc->isdn_linktab = ilt; +} + +/*---------------------------------------------------------------------------* + * initialize this drivers linktab + *---------------------------------------------------------------------------*/ +static void +tel_init_linktab(int unit) +{ + tel_sc_t *sc = &tel_sc[unit]; + + sc->drvr_linktab.unit = unit; + sc->drvr_linktab.bch_rx_data_ready = tel_rx_data_rdy; + sc->drvr_linktab.bch_tx_queue_empty = tel_tx_queue_empty; + sc->drvr_linktab.bch_activity = tel_activity; + sc->drvr_linktab.line_connected = tel_connect; + sc->drvr_linktab.line_disconnected = tel_disconnect; + sc->drvr_linktab.dial_response = tel_dialresponse; + sc->drvr_linktab.updown_ind = tel_updown; +} + +/*===========================================================================* + * AUDIO FORMAT CONVERSION + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * A-law to mu-law conversion + *---------------------------------------------------------------------------*/ +static unsigned char alaw_ulaw[] = { + 0x002a, 0x00a9, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0048, 0x00c8, + 0x0039, 0x00b9, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d7, + 0x0022, 0x00a1, 0x005b, 0x00dd, 0x001f, 0x009f, 0x0040, 0x00c0, + 0x0031, 0x00b1, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00cf, + 0x002e, 0x00ad, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004c, 0x00cc, + 0x003d, 0x00bd, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00db, + 0x0026, 0x00a5, 0x005d, 0x00df, 0x001f, 0x009f, 0x0044, 0x00c4, + 0x0035, 0x00b5, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d3, + 0x0028, 0x00a7, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0046, 0x00c6, + 0x0037, 0x00b7, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0053, 0x00d5, + 0x0020, 0x009f, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf, + 0x002f, 0x00af, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004d, 0x00ce, + 0x002c, 0x00ab, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004a, 0x00ca, + 0x003b, 0x00bb, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0057, 0x00d9, + 0x0024, 0x00a3, 0x005d, 0x00df, 0x001f, 0x009f, 0x0042, 0x00c2, + 0x0033, 0x00b3, 0x006b, 0x00ef, 0x001f, 0x009f, 0x004f, 0x00d1, + 0x002b, 0x00aa, 0x0063, 0x00e3, 0x001f, 0x009f, 0x0049, 0x00c9, + 0x003a, 0x00ba, 0x0077, 0x00f7, 0x001f, 0x009f, 0x0057, 0x00d7, + 0x0023, 0x00a2, 0x005d, 0x00dd, 0x001f, 0x009f, 0x0041, 0x00c1, + 0x0032, 0x00b2, 0x006b, 0x00eb, 0x001f, 0x009f, 0x004f, 0x00cf, + 0x002f, 0x00ae, 0x0067, 0x00e7, 0x001f, 0x009f, 0x004d, 0x00cd, + 0x003e, 0x00be, 0x00ff, 0x00ff, 0x001f, 0x009f, 0x005b, 0x00db, + 0x0027, 0x00a6, 0x005f, 0x00df, 0x001f, 0x009f, 0x0045, 0x00c5, + 0x0036, 0x00b6, 0x006f, 0x00ef, 0x001f, 0x009f, 0x0053, 0x00d3, + 0x0029, 0x00a8, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0047, 0x00c7, + 0x0038, 0x00b8, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d5, + 0x0021, 0x00a0, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf, + 0x0030, 0x00b0, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00ce, + 0x002d, 0x00ac, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004b, 0x00cb, + 0x003c, 0x00bc, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00d9, + 0x0025, 0x00a4, 0x005d, 0x00df, 0x001f, 0x009f, 0x0043, 0x00c3, + 0x0034, 0x00b4, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d1 +}; + +/*---------------------------------------------------------------------------* + * mu-law to A-law conversion + *---------------------------------------------------------------------------*/ +static unsigned char ulaw_alaw[] = { + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00ac, + 0x0050, 0x00d0, 0x0010, 0x0090, 0x0070, 0x00f0, 0x0030, 0x00b0, + 0x0040, 0x00c0, 0x0000, 0x0080, 0x0060, 0x00e0, 0x0020, 0x00a0, + 0x00d8, 0x0018, 0x0098, 0x0078, 0x00f8, 0x0038, 0x00b8, 0x0048, + 0x00c8, 0x0008, 0x0088, 0x0068, 0x00e8, 0x0028, 0x00a8, 0x00d6, + 0x0096, 0x0076, 0x00f6, 0x0036, 0x00b6, 0x0046, 0x00c6, 0x0006, + 0x0086, 0x0066, 0x00e6, 0x0026, 0x00a6, 0x00de, 0x009e, 0x00fe, + 0x00fe, 0x00be, 0x00be, 0x00ce, 0x00ce, 0x008e, 0x008e, 0x00ee, + 0x00ee, 0x00d2, 0x00d2, 0x00f2, 0x00f2, 0x00c2, 0x00c2, 0x00e2, + 0x00e2, 0x00e2, 0x00da, 0x00da, 0x00da, 0x00da, 0x00fa, 0x00fa, + 0x00fa, 0x00fa, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ea, 0x00ea, + 0x00ea, 0x00ea, 0x00ea, 0x00ea, 0x00eb, 0x00eb, 0x00eb, 0x00eb, + 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00d1, 0x0011, 0x0091, 0x0071, 0x00f1, 0x0031, 0x00b1, 0x0041, + 0x00c1, 0x0001, 0x0081, 0x0061, 0x00e1, 0x0021, 0x00a1, 0x0059, + 0x00d9, 0x0019, 0x0099, 0x0079, 0x00f9, 0x0039, 0x00b9, 0x0049, + 0x00c9, 0x0009, 0x0089, 0x0069, 0x00e9, 0x0029, 0x00a9, 0x0057, + 0x0017, 0x0097, 0x0077, 0x00f7, 0x0037, 0x00b7, 0x0047, 0x00c7, + 0x0007, 0x0087, 0x0067, 0x00e7, 0x0027, 0x00a7, 0x00df, 0x009f, + 0x009f, 0x00ff, 0x00ff, 0x00bf, 0x00bf, 0x00cf, 0x00cf, 0x008f, + 0x008f, 0x00ef, 0x00ef, 0x00af, 0x00af, 0x00d3, 0x00d3, 0x00f3, + 0x00f3, 0x00f3, 0x00c3, 0x00c3, 0x00c3, 0x00c3, 0x00e3, 0x00e3, + 0x00e3, 0x00e3, 0x00db, 0x00db, 0x00db, 0x00db, 0x00fb, 0x00fb, + 0x00fb, 0x00fb, 0x00fb, 0x00fb, 0x00cb, 0x00cb, 0x00cb, 0x00cb, + 0x00cb, 0x00cb, 0x00cb, 0x00cb, 0x00eb, 0x00eb, 0x00eb, 0x00eb +}; + +/*===========================================================================*/ + +#endif /* NI4BTEL > 0 */ diff --git a/sys/i4b/driver/i4b_trace.c b/sys/i4b/driver/i4b_trace.c new file mode 100644 index 0000000..f64e35d --- /dev/null +++ b/sys/i4b/driver/i4b_trace.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4btrc - device driver for trace data read device + * --------------------------------------------------- + * + * $Id: i4b_trace.c,v 1.14 1998/12/05 18:02:51 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:01:53 1998] + * + * NOTE: the code assumes that SPLI4B >= splimp ! + * + *---------------------------------------------------------------------------*/ + +#include "i4btrc.h" + +#if NI4BTRC > 0 + +#ifdef __FreeBSD__ +#include "isic.h" /* 'isic' is no pseudo-device on non FreeBSD - + * so we just can't count it at compile time, + * we're doing an attach-time check instead. */ + +#if NI4BTRC < NISIC +#error "number of trace devices != number of passive ISDN controllers !" +#error "change number of i4btrc to be equal to number of isic devices !" +#endif +#endif /* __FreeBSD__ */ + +#include <sys/param.h> +#include <sys/systm.h> + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/conf.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/proc.h> +#include <sys/tty.h> + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_trace.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_trace.h> +#include <i4b/i4b_ioctl.h> +#endif + +#ifndef __FreeBSD__ +#define memcpy(d,s,l) bcopy(s,d,l) +#endif + +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l3l4.h> + +static struct ifqueue trace_queue[NI4BTRC]; +static int device_state[NI4BTRC]; +#define ST_IDLE 0x00 +#define ST_ISOPEN 0x01 +#define ST_WAITDATA 0x02 +#ifdef DEVFS +static void *devfs_token[NI4BTRC]; +#endif + +static int analyzemode = 0; +static int rxunit = -1; +static int txunit = -1; +static int outunit = -1; + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* - not static - */ +void i4btrcattach __P((void)); +int i4btrcopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4btrcclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +int i4btrcread __P((dev_t dev, struct uio * uio, int ioflag)); +int i4btrcioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +#endif + +#if BSD > 199306 && defined(__FreeBSD__) +#define PDEVSTATIC static +static d_open_t i4btrcopen; +static d_close_t i4btrcclose; +static d_read_t i4btrcread; +static d_ioctl_t i4btrcioctl; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +static d_poll_t i4btrcpoll; +#endif + +#define CDEV_MAJOR 59 +static struct cdevsw i4btrc_cdevsw = { + i4btrcopen, i4btrcclose, i4btrcread, nowrite, + i4btrcioctl, nostop, noreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4btrcpoll, nommap, NULL, "i4btrc", NULL, -1 +#else + noselect, nommap, NULL, "i4btrc", NULL, -1 +#endif +}; + +/*---------------------------------------------------------------------------* + * interface init routine + *---------------------------------------------------------------------------*/ +static +void i4btrcinit(void *unused) +{ + dev_t dev; + + dev = makedev(CDEV_MAJOR, 0); + + cdevsw_add(&dev, &i4btrc_cdevsw, NULL); +} + +SYSINIT(i4btrcdev, SI_SUB_DRIVERS, + SI_ORDER_MIDDLE+CDEV_MAJOR, &i4btrcinit, NULL); + +static void i4btrcattach(void *); +PSEUDO_SET(i4btrcattach, i4b_trace); + +#endif /* BSD > 199306 && defined(__FreeBSD__) */ + +int get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf); + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4btrcattach(void *dummy) +#else +i4btrcattach() +#endif +{ + int i; + +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4btrc: %d ISDN trace device(s) attached\n", NI4BTRC); +#endif + + for(i=0; i < NI4BTRC; i++) + { +#ifdef DEVFS + devfs_token[i] + = devfs_add_devswf(&i4btrc_cdevsw, i, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4btrc%d", i); +#endif + trace_queue[i].ifq_maxlen = IFQ_MAXLEN; + device_state[i] = ST_IDLE; + } +} + +/*---------------------------------------------------------------------------* + * get_trace_data_from_l1() + * ------------------------ + * is called from layer 1, adds timestamp to trace data and puts + * it into a queue, from which it can be read from the i4btrc + * device. The unit number in the trace header selects the minor + * device's queue the data is put into. + *---------------------------------------------------------------------------*/ +int +get_trace_data_from_l1(i4b_trace_hdr_t *hdr, int len, char *buf) +{ + struct mbuf *m; + int x; + int unit; + int trunc = 0; + int totlen = len + sizeof(i4b_trace_hdr_t); + + /* + * for telephony (or better non-HDLC HSCX mode) we get + * (MCLBYTE + sizeof(i4b_trace_hdr_t)) length packets + * to put into the queue to userland. because of this + * we detect this situation, strip the length to MCLBYTES + * max size, and infor the userland program of this fact + * by putting the no of truncated bytes into hdr->trunc. + */ + + if(totlen > MCLBYTES) + { + trunc = 1; + hdr->trunc = totlen - MCLBYTES; + totlen = MCLBYTES; + } + else + { + hdr->trunc = 0; + } + + /* set length of trace record */ + + hdr->length = totlen; + + /* check valid unit no */ + + if((unit = hdr->unit) > NI4BTRC) + { + printf("i4b_trace: get_trace_data_from_l1 - unit > NI4BTRC!\n"); + return(0); + } + + /* get mbuf */ + + if(!(m = i4b_Bgetmbuf(totlen))) + { + printf("i4b_trace: get_trace_data_from_l1 - i4b_getmbuf() failed!\n"); + return(0); + } + + /* check if we are in analyzemode */ + + if(analyzemode && (unit == rxunit || unit == txunit)) + { + if(unit == rxunit) + hdr->dir = FROM_NT; + else + hdr->dir = FROM_TE; + unit = outunit; + } + + if(IF_QFULL(&trace_queue[unit])) + { + struct mbuf *m1; + + x = SPLI4B(); + IF_DEQUEUE(&trace_queue[unit], m1); + splx(x); + + i4b_Bfreembuf(m1); + } + + /* copy trace header */ + memcpy(m->m_data, hdr, sizeof(i4b_trace_hdr_t)); + + /* copy trace data */ + if(trunc) + memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, totlen-sizeof(i4b_trace_hdr_t)); + else + memcpy(&m->m_data[sizeof(i4b_trace_hdr_t)], buf, len); + + x = SPLI4B(); + + IF_ENQUEUE(&trace_queue[unit], m); + + if(device_state[unit] & ST_WAITDATA) + { + device_state[unit] &= ~ST_WAITDATA; + wakeup((caddr_t) &trace_queue[unit]); + } + + splx(x); + + return(1); +} + +/*---------------------------------------------------------------------------* + * open trace device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btrcopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int x; + int unit = minor(dev); + + if(unit > NI4BTRC) + return(ENXIO); + + if(device_state[unit] & ST_ISOPEN) + return(EBUSY); + + if(analyzemode && (unit == outunit || unit == rxunit || unit == txunit)) + return(EBUSY); + + x = SPLI4B(); + + device_state[unit] = ST_ISOPEN; + + splx(x); + + return(0); +} + +/*---------------------------------------------------------------------------* + * close trace device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btrcclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + int unit = minor(dev); + int i, x, cno = -1; + + for(i = 0; i < nctrl; i++) + { + if(ctrl_desc[i].N_SET_TRACE) + { + cno = i; + break; + } + } + + if(analyzemode && (unit == outunit)) + { + analyzemode = 0; + outunit = -1; + + if(cno >= 0) + { + ctrl_desc[cno].N_SET_TRACE(rxunit, TRACE_OFF); + ctrl_desc[cno].N_SET_TRACE(txunit, TRACE_OFF); + } + rxunit = -1; + txunit = -1; + } + + if(cno >= 0) + { + ctrl_desc[cno].N_SET_TRACE(unit, TRACE_OFF); + } + + x = SPLI4B(); + device_state[unit] = ST_IDLE; + splx(x); + + return(0); +} + +/*---------------------------------------------------------------------------* + * read from trace device + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4btrcread(dev_t dev, struct uio * uio, int ioflag) +{ + struct mbuf *m; + int x; + int error = 0; + int unit = minor(dev); + + if(!(device_state[unit] & ST_ISOPEN)) + return(EIO); + + x = SPLI4B(); + + while(IF_QEMPTY(&trace_queue[unit]) && (device_state[unit] & ST_ISOPEN)) + { + device_state[unit] |= ST_WAITDATA; + + if((error = tsleep((caddr_t) &trace_queue[unit], + TTIPRI | PCATCH, + "bitrc", 0 )) != 0) + { + device_state[unit] &= ~ST_WAITDATA; + splx(x); + return(error); + } + } + + IF_DEQUEUE(&trace_queue[unit], m); + + if(m && m->m_len) + error = uiomove(m->m_data, m->m_len, uio); + else + error = EIO; + + if(m) + i4b_Bfreembuf(m); + + splx(x); + + return(error); +} + +/*---------------------------------------------------------------------------* + * poll device + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +PDEVSTATIC int +i4btrcpoll(dev_t dev, int events, struct proc *p) +{ + return(ENODEV); +} +#endif + +/*---------------------------------------------------------------------------* + * device driver ioctl routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003 +i4btrcioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +#else +i4btrcioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) +#endif +{ + int error = 0; + int unit = minor(dev); + i4b_trace_setupa_t *tsa; + int i, cno = -1; + + /* find the first passive controller to get at the set/get function + pointers. Would be better if we had the controller class virtual + function table separate from the port registry... */ + + for(i=0; i < nctrl; i++) + { + if(ctrl_desc[i].N_SET_TRACE) + { + cno = i; /* one suitable controller, might not */ + break; /* be related to the trace unit at all, but */ + } /* has the right function pointers */ + } + + switch(cmd) + { + case I4B_TRC_GET: + if(cno < 0) + return ENOTTY; + *(int *)data = ctrl_desc[cno].N_GET_TRACE(unit); + break; + + case I4B_TRC_SET: + if(cno < 0) + return ENOTTY; + ctrl_desc[cno].N_SET_TRACE(unit, *(int *)data); + break; + + case I4B_TRC_SETA: + tsa = (i4b_trace_setupa_t *)data; + + if(tsa->rxunit >= 0 && tsa->rxunit < NI4BTRC) + rxunit = tsa->rxunit; + else + error = EINVAL; + + if(tsa->txunit >= 0 && tsa->txunit < NI4BTRC) + txunit = tsa->txunit; + else + error = EINVAL; + + if(error) + { + outunit = -1; + rxunit = -1; + txunit = -1; + } + else + { + if(cno < 0) + return ENOTTY; + + outunit = unit; + analyzemode = 1; + ctrl_desc[cno].N_SET_TRACE(rxunit, tsa->rxflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)); + ctrl_desc[cno].N_SET_TRACE(txunit, tsa->txflags & (TRACE_I | TRACE_D_RX | TRACE_B_RX)); + } + break; + + case I4B_TRC_RESETA: + analyzemode = 0; + outunit = -1; + rxunit = -1; + txunit = -1; + break; + + default: + error = ENOTTY; + break; + } + return(error); +} + +#endif /* NI4BTRC > 0 */ diff --git a/sys/i4b/include/i4b_cause.h b/sys/i4b/include/i4b_cause.h new file mode 100644 index 0000000..439db4e --- /dev/null +++ b/sys/i4b/include/i4b_cause.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_cause.h - causes and cause handling for i4b + * ----------------------------------------------- + * + * $Id: i4b_cause.h,v 1.8 1998/12/05 18:05:55 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:30 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_CAUSE_H_ +#define _I4B_CAUSE_H_ + +/*---------------------------------------------------------------------------* + * ISDN4BSD internal causes specification + *---------------------------------------------------------------------------*/ + +#define CAUSE_VAL 0x000000ff /* cause value */ +#define CAUSE_TYPE 0x0000ff00 /* cause type */ +#define CAUSET_Q850 0 /* value coded according to Q.850 */ +#define CAUSET_I4B 1 /* i4b protocol independent causes*/ + +#define GET_CAUSE_VAL(cause) ((cause) & 0xff) +#define SET_CAUSE_VAL(dest, val) ((dest) = ((dest & 0xffffff00) | \ + (val & 0x000000ff))) + +#define GET_CAUSE_TYPE(cause) (((cause) >> 8) & 0xff) +#define SET_CAUSE_TYPE(dest, type) ((dest) = ((dest & 0xffff00ff) | \ + ((type << 8) & 0x0000ff00))) + +#define SET_CAUSE_TV(dest, type, val) ((dest) = ((val & 0x000000ff) | \ + ((type << 8) & 0x0000ff00))) + +/* CAUSET_I4B - protocol independent cause values */ + +#define CAUSE_I4B_NORMAL 0 /* normal call clearing */ +#define CAUSE_I4B_BUSY 1 /* user busy */ +#define CAUSE_I4B_NOCHAN 2 /* circuit/channel not available*/ +#define CAUSE_I4B_INCOMP 3 /* incompatible source/dest */ +#define CAUSE_I4B_REJECT 4 /* call rejected */ +#define CAUSE_I4B_OOO 5 /* destination out of order */ +#define CAUSE_I4B_TMPFAIL 6 /* temporary failure */ +#define CAUSE_I4B_L1ERROR 7 /* L1 error / persistent deact */ +#define CAUSE_I4B_MAX 8 + +/* CAUSET_Q850 - causes defined in Q.850 */ + +#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */ +#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */ +#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */ +#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */ +#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */ +#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */ +#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */ +#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */ +#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */ +#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */ +#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */ +#define CAUSE_Q850_USRBSY 0x11 /* User busy */ +#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */ +#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */ +#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */ +#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */ +#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */ +#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */ +#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */ +#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */ +#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */ +#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */ +#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */ +#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */ +#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */ +#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */ +#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */ +#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */ +#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */ +#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */ +#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */ +#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */ +#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */ +#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */ +#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */ +#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */ +#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */ +#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */ +#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */ +#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */ +#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */ +#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */ +#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */ +#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */ +#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */ +#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */ +#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */ +#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */ +#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */ +#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */ +#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */ +#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */ +#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */ +#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */ +#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */ +#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */ +#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */ +#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */ +#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */ +#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */ +#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */ +#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */ +#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */ +#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */ +#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */ +#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */ +#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */ +#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */ + +#define CAUSE_Q850_MAX 128 + +#endif /* _I4B_CAUSE_H_ */ diff --git a/sys/i4b/include/i4b_debug.h b/sys/i4b/include/i4b_debug.h new file mode 100644 index 0000000..33e6315 --- /dev/null +++ b/sys/i4b/include/i4b_debug.h @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_debug.h - i4b debug header file + * ----------------------------------- + * + * $Id: i4b_debug.h,v 1.14 1998/12/05 18:05:57 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:47 1998] + * + *---------------------------------------------------------------------------*/ + +#define DO_I4B_DEBUG /* enable debugging code inclusion */ + +#undef DO_I4B_MAXDEBUG /* enable ALL debug messages by default */ + +#ifdef DO_I4B_DEBUG + +extern unsigned int i4b_l1_debug; +extern unsigned int i4b_l2_debug; +extern unsigned int i4b_l3_debug; +extern unsigned int i4b_l4_debug; + +#define DBGL1(bits, routine, what) \ + if(bits & i4b_l1_debug) \ + { \ + printf("i4b-L1-%s: ", routine); \ + printf what ; \ + } + +#define DBGL2(bits, routine, what) \ + if(bits & i4b_l2_debug) \ + { \ + printf("i4b-L2-%s: ", routine); \ + printf what ; \ + } + +#define DBGL3(bits, routine, what) \ + if(bits & i4b_l3_debug) \ + { \ + printf("i4b-L3-%s: ", routine); \ + printf what ; \ + } + +#define DBGL4(bits, routine, what) \ + if(bits & i4b_l4_debug) \ + { \ + printf("i4b-L4-%s: ", routine); \ + printf what ; \ + } +#else /* !DO_I4B_DEBUG */ + +#define DBGL1(bits, routine, what); +#define DBGL2(bits, routine, what); +#define DBGL3(bits, routine, what); +#define DBGL4(bits, routine, what); + +#endif /* DO_I4B_DEBUG */ + +/* Layer 1 */ + +#define L1_ERROR 0x0001 /* general error message*/ +#define L1_PRIM 0x0002 /* interlayer primitives*/ +#define L1_BCHAN 0x0004 /* B channel action */ +#define L1_H_ERR 0x0008 /* HSCX errors */ +#define L1_H_IRQ 0x0010 /* HSCX IRQ messages */ +#define L1_I_ERR 0x0020 /* ISAC errors */ +#define L1_I_MSG 0x0040 /* ISAC messages */ +#define L1_I_SETUP 0x0080 /* ISAC setup messages */ +#define L1_F_MSG 0x0100 /* FSM messages */ +#define L1_F_ERR 0x0200 /* FSM error messages */ +#define L1_T_MSG 0x0400 /* Timer messages */ +#define L1_T_ERR 0x0800 /* Timer error messages */ +#define L1_H_XFRERR 0x1000 /* HSCX data xfer error */ +#define L1_I_CICO 0x2000 /* ISAC command in/out */ + +#define L1_DEBUG_MAX 0x3fef /* all messages on except IRQ! */ +#define L1_DEBUG_ERR (L1_H_ERR | L1_I_ERR | L1_F_ERR | L1_T_ERR | L1_ERROR) + +#ifndef L1_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L1_DEBUG_DEFAULT L1_DEBUG_MAX +#else +#define L1_DEBUG_DEFAULT L1_DEBUG_ERR +#endif +#endif + +/* Layer 2 */ + +#define L2_ERROR 0x0001 /* general error message */ +#define L2_PRIM 0x0002 /* interlayer primitives */ +#define L2_U_MSG 0x0004 /* U frame messages */ +#define L2_U_ERR 0x0008 /* U frame error messages */ +#define L2_S_MSG 0x0010 /* S frame messages */ +#define L2_S_ERR 0x0020 /* S frame error messages */ +#define L2_I_MSG 0x0040 /* I frame messages */ +#define L2_I_ERR 0x0080 /* I frame error messages */ +#define L2_F_MSG 0x0100 /* FSM messages */ +#define L2_F_ERR 0x0200 /* FSM error messages */ +#define L2_T_MSG 0x0400 /* timer messages */ +#define L2_T_ERR 0x0800 /* timer error messages */ +#define L2_TEI_MSG 0x1000 /* TEI messages */ +#define L2_TEI_ERR 0x2000 /* TEI error messages */ + +#define L2_DEBUG_MAX 0x3fff /* all messages on */ +#define L2_DEBUG_ERR (L2_ERROR | L2_I_ERR | L2_F_ERR | L2_T_ERR | L2_S_ERR | L2_TEI_ERR | L2_U_ERR ) + +#ifndef L2_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L2_DEBUG_DEFAULT L2_DEBUG_MAX +#else +#define L2_DEBUG_DEFAULT L2_DEBUG_ERR +#endif +#endif + +/* Layer 3 */ + +#define L3_ERR 0x0001 /* general error message */ +#define L3_MSG 0x0002 /* general message */ +#define L3_F_MSG 0x0004 /* FSM messages */ +#define L3_F_ERR 0x0008 /* FSM error messages */ +#define L3_T_MSG 0x0010 /* timer messages */ +#define L3_T_ERR 0x0020 /* timer error messages */ +#define L3_P_MSG 0x0040 /* protocol messages */ +#define L3_P_ERR 0x0080 /* protocol error messages */ +#define L3_A_MSG 0x0100 /* AOC messages */ +#define L3_A_ERR 0x0200 /* AOC error messages */ +#define L3_PRIM 0x0400 /* messages exchanged */ + +#define L3_DEBUG_MAX 0x07ff /* all messages on */ +#define L3_DEBUG_ERR (L3_ERR | L3_F_ERR | L3_T_ERR | L3_P_ERR | L3_A_ERR) + +#ifndef L3_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L3_DEBUG_DEFAULT L3_DEBUG_MAX +#else +#define L3_DEBUG_DEFAULT L3_DEBUG_ERR +#endif +#endif + +/* Layer 4 */ + +#define L4_ERR 0x0001 /* general error message */ +#define L4_MSG 0x0002 /* general message */ +#define L4_TIMO 0x0004 /* b channel idle timeout msgs */ +#define L4_DIALST 0x0008 /* network driver dial states */ +#define L4_IPRDBG 0x0010 /* ipr driver debug messages */ +#define L4_RBCHDBG 0x0020 /* rbch driver debug messages */ + +#define L4_DEBUG_MAX 0x003f /* all messages on */ +#define L4_DEBUG_ERR (L4_ERR) + +#ifndef L4_DEBUG_DEFAULT +#ifdef DO_I4B_MAXDEBUG +#define L4_DEBUG_DEFAULT L4_DEBUG_MAX +#else +#define L4_DEBUG_DEFAULT L4_DEBUG_ERR +#endif +#endif + +/*---------------------------------------------------------------------------* + * ioctl via /dev/i4bctl: + * get/set current debug bits settings + *---------------------------------------------------------------------------*/ + +typedef struct { + unsigned int l1; + unsigned int l2; + unsigned int l3; + unsigned int l4; +} ctl_debug_t; + +#define I4B_CTL_GET_DEBUG _IOR('C', 0, ctl_debug_t) + +#define I4B_CTL_SET_DEBUG _IOW('C', 1, ctl_debug_t) + +/*---------------------------------------------------------------------------* + * get hscx statistics + *---------------------------------------------------------------------------*/ + +typedef struct { + int unit; /* controller number */ + int chan; /* channel number */ + int vfr; + int rdo; + int crc; + int rab; + int xdu; + int rfo; +} hscxstat_t; + +#define I4B_CTL_GET_HSCXSTAT _IOWR('C', 2, hscxstat_t) + +#define I4B_CTL_CLR_HSCXSTAT _IOW('C', 3, hscxstat_t) + +/* EOF */ diff --git a/sys/i4b/include/i4b_global.h b/sys/i4b/include/i4b_global.h new file mode 100644 index 0000000..739d78d --- /dev/null +++ b/sys/i4b/include/i4b_global.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_global.h - i4b global include file + * -------------------------------------- + * + * $Id: i4b_global.h,v 1.17 1998/12/05 18:02:53 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:03:41 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_GLOBAL_H_ +#define _I4B_GLOBAL_H_ + +#define SPLI4B() splimp() /* spl for i4b */ + +#define TIMER_IDLE 1 /* a timer is running */ +#define TIMER_ACTIVE 2 /* a timer is idle */ + +#ifdef __FreeBSD__ +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + +#define TIMEOUT_FUNC_T timeout_t * +#define SECOND time_second +#define MICROTIME(x) getmicrotime(&(x)) + +#else /* FreeBSD < 3 */ + +#define TIMEOUT_FUNC_T timeout_func_t +#define SECOND time.tv_sec +#define MICROTIME(x) microtime(&(x)) + +#endif /* >= 3 */ +#endif /* __FreeBSD__ */ + +#if defined(__NetBSD__) || defined (__OpenBSD__) + +#define TIMEOUT_FUNC_T void * +#define SECOND time.tv_sec +#define MICROTIME(x) (x) = time + +#endif /* __NetBSD__ */ + +/* definitions for the STATUS indications L1 -> L2 -> L3 */ + +#define STI_ATTACH 0 /* attach at boot time */ +#define STI_L1STAT 1 /* layer 1 status */ +#define STI_L2STAT 2 /* layer 2 status */ +#define STI_TEIASG 3 /* TEI assignments */ +#define STI_PDEACT 4 /* Layer 1 T4 expired = persistent deactivation */ +#define STI_NOL1ACC 5 /* no outgoing L1 access possible */ + +/* definitions for the COMMAND requests L3 -> L2 -> L1 */ + +#define CMR_DOPEN 0 /* daemon opened /dev/i4b */ +#define CMR_DCLOSE 1 /* daemon closed /dev/i4b */ + +/*--------------------------------------------------------------------------- + * + * Number of max supported passive card units + * + * Teles/Creatix/Neuhaus cards have a hardware limitation + * as one is able to set 3 (sometimes 4) different configurations by + * jumpers so a maximum of 3 (4) cards per ISA bus is possible. + * (Note: there are multiple ISA buses on some architectures) + * + *---------------------------------------------------------------------------*/ +#define ISIC_MAXUNIT 3 /* max no of supported units 0..3 */ + +#endif /* _I4B_GLOBAL_H_ */ diff --git a/sys/i4b/include/i4b_ioctl.h b/sys/i4b/include/i4b_ioctl.h new file mode 100644 index 0000000..17e945f --- /dev/null +++ b/sys/i4b/include/i4b_ioctl.h @@ -0,0 +1,606 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ioctl.h - messages kernel <--> userland + * ------------------------------------------- + * + * $Id: i4b_ioctl.h,v 1.58 1998/12/22 19:48:24 hm Exp $ + * + * last edit-date: [Tue Dec 22 20:33:46 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_IOCTL_H_ +#define _I4B_IOCTL_H_ + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#ifndef _MACHINE_TYPES_H_ +#include <machine/types.h> +#endif /* _MACHINE_TYPES_H_ */ +#endif /* __FreeBSD__ */ + +/*---------------------------------------------------------------------------* + * version and release number for isdn4bsd package + *---------------------------------------------------------------------------*/ +#define VERSION 0 /* version number */ +#define REL 70 /* release number */ +#define STEP 00 /* release step */ + +/*---------------------------------------------------------------------------* + * date/time format in i4b log messages + * ------------------------------------ + * Being year 2000 clean is not easy with the current state of the + * ANSI C library standard and it's implementation for some locales. + * You might like to use the "%c" format of "strftime" sometimes, + * but this breaks Y2K in some locales. Also the old standard logfile + * format "%d.%m.%y %H:%M:%S" is non compliant. + * NetBSD's current toolset warns about this problems, and we compile + * with -Werror, so this problems need to be resolved. + *---------------------------------------------------------------------------*/ +#define I4B_TIME_FORMAT "%d.%m.%Y %H:%M:%S" + +/*---------------------------------------------------------------------------* + * max number of controllers in system + *---------------------------------------------------------------------------*/ +#define MAX_CONTROLLERS 8 /* max number of controllers */ + +/*---------------------------------------------------------------------------* + * controller types + *---------------------------------------------------------------------------*/ +#define CTRL_INVALID (-1) /* invalid, error */ +#define CTRL_UNKNOWN 0 /* unknown controller type */ +#define CTRL_PASSIVE 1 /* passive ISDN controller cards*/ +#define CTRL_DAIC 2 /* Diehl active controller cards*/ +#define CTRL_NUMTYPES 3 /* number of controller types */ + +/*---------------------------------------------------------------------------* + * card types for CTRL_PASSIVE + *---------------------------------------------------------------------------*/ +#define CARD_TYPEP_INVAL (-1) /* invalid, error */ +#define CARD_TYPEP_UNK 0 /* unknown */ +#define CARD_TYPEP_8 1 /* Teles, S0/8 */ +#define CARD_TYPEP_16 2 /* Teles, S0/16 */ +#define CARD_TYPEP_16_3 3 /* Teles, S0/16.3 */ +#define CARD_TYPEP_AVMA1 4 /* AVM A1 or AVM Fritz!Card */ +#define CARD_TYPEP_163P 5 /* Teles, S0/16.3 PnP */ +#define CARD_TYPEP_CS0P 6 /* Creatix, S0 PnP */ +#define CARD_TYPEP_USRTA 7 /* US Robotics ISDN TA internal */ +#define CARD_TYPEP_DRNNGO 8 /* Dr. Neuhaus Niccy GO@ */ +#define CARD_TYPEP_SWS 9 /* Sedlbauer Win Speed */ +#define CARD_TYPEP_DYNALINK 10 /* Dynalink IS64PH */ +#define CARD_TYPEP_BLMASTER 11 /* ISDN Blaster / ISDN Master */ +#define CARD_TYPEP_PCFRITZ 12 /* AVM PCMCIA Fritz!Card */ +#define CARD_TYPEP_ELSAQS1ISA 13 /* ELSA QuickStep 1000pro ISA */ +#define CARD_TYPEP_ELSAQS1PCI 14 /* ELSA QuickStep 1000pro PCI */ +#define CARD_TYPEP_SIEMENSITALK 15 /* Siemens I-Talk */ +#define CARD_TYPEP_ELSAMLIMC 16 /* ELSA MicroLink ISDN/MC */ +#define CARD_TYPEP_ELSAMLMCALL 17 /* ELSA MicroLink MCall */ +#define CARD_TYPEP_ITKIX1 18 /* ITK ix1 micro */ + +/* + * in case you add support for more cards, please update: + * + * isdnd: support.c, name_of_controller() + * diehl/diehlctl: main.c, listall() + * + * and adjust CARD_TYPEP_MAX below. + */ + +#define CARD_TYPEP_MAX 18 /* max type */ + +/*---------------------------------------------------------------------------* + * card types for CTRL_DAIC + *---------------------------------------------------------------------------*/ +#define CARD_TYPEA_DAIC_UNK 0 +#define CARD_TYPEA_DAIC_S 1 +#define CARD_TYPEA_DAIC_SX 2 +#define CARD_TYPEA_DAIC_SCOM 3 +#define CARD_TYPEA_DAIC_QUAD 4 + +/*---------------------------------------------------------------------------* + * max length of some strings + *---------------------------------------------------------------------------*/ +#define TELNO_MAX 41 /* max length of a telephone number (+ '\0') */ +#define DISPLAY_MAX 91 /* max length of display information (+ '\0') */ +#define DATETIME_MAX 21 /* max length of datetime information (+ '\0')*/ + +/*---------------------------------------------------------------------------* + * in case the src or dst telephone number is empty + *---------------------------------------------------------------------------*/ +#define TELNO_EMPTY "NotAvailable" + +/*---------------------------------------------------------------------------* + * B channel parameters + *---------------------------------------------------------------------------*/ +#define BCH_MAX_DATALEN 2048 /* max length of a B channel frame */ + +/*---------------------------------------------------------------------------* + * userland driver types + * --------------------- + * a "driver" is defined here as a piece of software interfacing an + * ISDN B channel with a userland service, such as IP, Telephony etc. + *---------------------------------------------------------------------------*/ +#define BDRV_RBCH 0 /* raw b-channel interface driver */ +#define BDRV_TEL 1 /* telephone (speech) interface driver */ +#define BDRV_IPR 2 /* IP over raw HDLC interface driver */ +#define BDRV_ISPPP 3 /* sync Kernel PPP interface driver */ + +/*---------------------------------------------------------------------------* + * B channel protocol + *---------------------------------------------------------------------------*/ +#define BPROT_NONE 0 /* no protocol at all, raw data */ +#define BPROT_RHDLC 1 /* raw HDLC: flag, data, crc, flag */ + +/*---------------------------------------------------------------------------* + * causes data type + *---------------------------------------------------------------------------*/ +typedef unsigned int cause_t; /* 32 bit unsigned int */ + +/*---------------------------------------------------------------------------* + * call descriptor id (cdid) definitions + *---------------------------------------------------------------------------*/ +#define CDID_UNUSED 0 /* cdid is invalid and unused */ +#define CDID_MAX 99999 /* highest valid cdid, wraparound to 1 */ + + +/**************************************************************************** + + outgoing call: + -------------- + + userland kernel + -------- ------ + + CDID_REQ -----------------> + + <------------------ cdid + + CONNECT_REQ --------------> + + <------------------ PROCEEDING_IND (if connect req ok) + + <------------------ CONNECT_ACTIVE_IND (if connection ok) + + or + + <------------------ DISCONNECT_IND (if connection failed) + + + + incoming call: + -------------- + + userland kernel + -------- ------ + + <------------------ CONNECT_IND + + CONNECT_RESP -------------> + + <------------------ CONNECT_ACTIVE_IND (if accepted) + + + + active disconnect: + ------------------ + + userland kernel + -------- ------ + + DISCONNECT_REQ ------------> + + <------------------ DISCONNECT_IND + + + passive disconnect: + ------------------- + + userland kernel + -------- ------ + + <------------------ DISCONNECT_IND + + +****************************************************************************/ + + +/*===========================================================================* + *===========================================================================* + * "read" messages from kernel -> userland + *===========================================================================* + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * message header, included in every message + *---------------------------------------------------------------------------*/ +typedef struct { + char type; /* message identifier */ +#define MSG_CONNECT_IND 'a' +#define MSG_CONNECT_ACTIVE_IND 'b' +#define MSG_DISCONNECT_IND 'c' +#define MSG_DIALOUT_IND 'd' +#define MSG_IDLE_TIMEOUT_IND 'e' +#define MSG_ACCT_IND 'f' +#define MSG_CHARGING_IND 'g' +#define MSG_PROCEEDING_IND 'h' +#define MSG_ALERT_IND 'i' +#define MSG_DRVRDISC_REQ 'j' +#define MSG_L12STAT_IND 'k' +#define MSG_TEIASG_IND 'l' +#define MSG_PDEACT_IND 'm' +#define MSG_NEGCOMP_IND 'n' +#define MSG_IFSTATE_CHANGED_IND 'o' + int cdid; /* call descriptor id */ +} msg_hdr_t; + +/*---------------------------------------------------------------------------* + * connect indication + * indicates incoming connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number */ + int channel; /* channel number */ +#define CHAN_B1 0 /* this _must_ be 0, HSCX B1 is also 0 */ +#define CHAN_B2 1 /* this _must_ be 1, HSCX B2 is also 1 */ +#define CHAN_ANY (-1) /* outgoing, not possible for incoming */ +#define CHAN_NO (-2) /* call waiting (CW) for incoming */ + int bprot; /* b channel protocot, see BPROT_XXX */ + char dst_telno[TELNO_MAX]; /* destination telno */ + char src_telno[TELNO_MAX]; /* source telno */ + int scr_ind;/* screening indicator */ +#define SCR_NONE 0 /* no screening indicator transmitted */ +#define SCR_USR_NOSC 1 /* screening user provided, not screened*/ +#define SCR_USR_PASS 2 /* screening user provided, verified & passed */ +#define SCR_USR_FAIL 3 /* screening user provided, verified & failed */ +#define SCR_NET 4 /* screening network provided */ + char display[DISPLAY_MAX]; /* content of display IE*/ +} msg_connect_ind_t; + +/*---------------------------------------------------------------------------* + * connect active indication + * indicates active connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number actually used */ + int channel; /* channel number actually used */ + char datetime[DATETIME_MAX]; /* content of date/time IE */ +} msg_connect_active_ind_t; + +/*---------------------------------------------------------------------------* + * disconnect indication + * indicates a disconnect + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + cause_t cause; /* cause code */ +} msg_disconnect_ind_t; + +/*---------------------------------------------------------------------------* + * negotiation complete + * indicates an interface is completely up & running + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_negcomplete_ind_t; + +/*---------------------------------------------------------------------------* + * interface changes internal state + * indicates an interface has somehow switched its FSM + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int state; /* new interface state */ +} msg_ifstatechg_ind_t; + +/*---------------------------------------------------------------------------* + * initiate a call to a remote site + * i.e. the IP driver got a packet and wants a connection + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int driver; /* driver type */ + int driver_unit; /* driver unit number */ +} msg_dialout_ind_t; + +/*---------------------------------------------------------------------------* + * idle timeout disconnect sent indication + * kernel has sent disconnect request because of b-ch idle + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_idle_timeout_ind_t; + +/*---------------------------------------------------------------------------* + * accounting information from userland interface driver to daemon + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int accttype; /* accounting type */ +#define ACCT_DURING 0 +#define ACCT_FINAL 1 + int driver; /* driver type */ + int driver_unit; /* driver unit number */ + int ioutbytes; /* ISDN # of bytes sent */ + int iinbytes; /* ISDN # of bytes received */ + int outbps; /* bytes per sec out */ + int inbps; /* bytes per sec in */ + int outbytes; /* driver # of bytes sent */ + int inbytes; /* driver # of bytes received */ +} msg_accounting_ind_t; + +/*---------------------------------------------------------------------------* + * charging information from isdn driver to daemon + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int units; /* number of units */ + int units_type; /* type of units info */ +#define CHARGE_INVALID 0 /* invalid, unknown */ +#define CHARGE_AOCD 1 /* advice of charge during call */ +#define CHARGE_AOCE 2 /* advice of charge at end of call */ +#define CHARGE_CALC 3 /* locally calculated from rates information */ +} msg_charging_ind_t; + +/*---------------------------------------------------------------------------* + * call proceeding indication + * indicates outgoing SETUP has been acknowleged + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller number actually used */ + int channel; /* channel number actually used */ +} msg_proceeding_ind_t; + +/*---------------------------------------------------------------------------* + * alert indication + * indicates remote user side "rings" + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ +} msg_alert_ind_t; + +/*---------------------------------------------------------------------------* + * driver requests to disconnect line + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int driver; /* driver type */ + int driver_unit; /* driver unit number */ +} msg_drvrdisc_req_t; + +/*---------------------------------------------------------------------------* + * state of layer 1/2 + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int layer; /* layer number (1/2) */ +#define LAYER_ONE 1 +#define LAYER_TWO 2 + int state; /* state info */ +#define LAYER_IDLE 0 +#define LAYER_ACTIVE 1 +} msg_l12stat_ind_t; + +/*---------------------------------------------------------------------------* + * TEI assignment messages + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int tei; /* TEI or -1 if invalid */ +} msg_teiasg_ind_t; + +/*---------------------------------------------------------------------------* + * persistent deactivation state of stack + *---------------------------------------------------------------------------*/ +typedef struct { + msg_hdr_t header; /* common header */ + int controller; /* controller unit */ + int numactive; /* number of active connections */ +} msg_pdeact_ind_t; + + +/*===========================================================================* + *===========================================================================* + * "ioctl" messages from userland -> kernel + *===========================================================================* + *===========================================================================*/ + + +/*---------------------------------------------------------------------------* + * request a unique cdid (to setup an outgoing call) + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ +} msg_cdid_req_t; + +#define I4B_CDID_REQ _IOWR('4', 0, int) + +/*---------------------------------------------------------------------------* + * connect request + * requests an outgoing connection + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int controller; /* controller to use */ + int channel; /* channel to use */ + int txdelay; /* tx delay after connect */ + int bprot; /* b channel protocol */ + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int unitlen_time; /* length of a charging unit */ + int idle_time; /* time without activity on b ch */ + int earlyhup_time; /* safety area at end of unit */ + int unitlen_method; /* how to calculate the unitlength */ +#define ULEN_METHOD_STATIC 0 /* use unitlen_time value (see above) */ +#define ULEN_METHOD_DYNAMIC 1 /* use AOCD */ + char dst_telno[TELNO_MAX]; /* destination telephone no */ + char src_telno[TELNO_MAX]; /* source telephone number */ +} msg_connect_req_t; + +#define I4B_CONNECT_REQ _IOW('4', 1, msg_connect_req_t) + +/*---------------------------------------------------------------------------* + * connect response + * this is the answer to an incoming connect indication + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int response; /* what to do with incoming call */ +#define SETUP_RESP_DNTCRE 0 /* dont care, call is not for me */ +#define SETUP_RESP_REJECT 1 /* reject call */ +#define SETUP_RESP_ACCEPT 2 /* accept call */ + cause_t cause; /* cause for case SETUP_RESP_REJECT */ + /* the following are only used for SETUP_RESP_ACCEPT !! */ + int txdelay; /* tx delay after connect */ + int bprot; /* B chan protocol */ + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int max_idle_time; /* max time without activity on b ch */ +} msg_connect_resp_t; + +#define I4B_CONNECT_RESP _IOW('4', 2, msg_connect_resp_t) + +/*---------------------------------------------------------------------------* + * disconnect request + * active disconnect request + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + cause_t cause; /* protocol independent cause */ +} msg_discon_req_t; + +#define I4B_DISCONNECT_REQ _IOW('4', 3, msg_discon_req_t) + +/*---------------------------------------------------------------------------* + * controller info request + *---------------------------------------------------------------------------*/ +typedef struct { + int controller; /* controller number */ + int ncontroller; /* number of controllers in system */ + int ctrl_type; /* controller type passive/active */ + int card_type; /* brand / version */ + int tei; /* tei controller probably has */ +} msg_ctrl_info_req_t; + +#define I4B_CTRL_INFO_REQ _IOWR('4', 4, msg_ctrl_info_req_t) + +/*---------------------------------------------------------------------------* + * dialout response + * status report to driver who requested a dialout + *---------------------------------------------------------------------------*/ +typedef struct { + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int stat; /* state of dialout request */ +#define DSTAT_NONE 0 +#define DSTAT_TFAIL 1 /* transient failure */ +#define DSTAT_PFAIL 2 /* permanent failure */ +#define DSTAT_INONLY 3 /* no outgoing dials allowed */ +} msg_dialout_resp_t; + +#define I4B_DIALOUT_RESP _IOW('4', 5, msg_dialout_resp_t) + +/*---------------------------------------------------------------------------* + * timeout value update + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ + int unitlen_time; /* length of a charging unit */ + int idle_time; /* time without activity on b ch */ + int earlyhup_time; /* safety area at end of unit */ +} msg_timeout_upd_t; + +#define I4B_TIMEOUT_UPD _IOW('4', 6, msg_timeout_upd_t) + +/*---------------------------------------------------------------------------* + * soft enable/disable + *---------------------------------------------------------------------------*/ +typedef struct { + int driver; /* driver to route b channel data to */ + int driver_unit; /* unit number for above driver */ + int updown; /* what to do */ +#define SOFT_ENA 0 /* enable interface */ +#define SOFT_DIS 1 /* disable interface */ +} msg_updown_ind_t; + +#define I4B_UPDOWN_IND _IOW('4', 7, msg_updown_ind_t) + +/*---------------------------------------------------------------------------* + * send alert request + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call descriptor id */ +} msg_alert_req_t; + +#define I4B_ALERT_REQ _IOW('4', 8, msg_alert_req_t) + +/*---------------------------------------------------------------------------* + * request version and release info from kernel part + *---------------------------------------------------------------------------*/ +typedef struct { + int version; /* version number */ + int release; /* release number */ + int step; /* release step number */ +} msg_vr_req_t; + +#define I4B_VR_REQ _IOR('4', 9, msg_vr_req_t) + +/*---------------------------------------------------------------------------* + * Protocol download to active cards + *---------------------------------------------------------------------------*/ +struct isdn_dr_prot { + size_t bytecount; /* length of code */ + u_int8_t *microcode; /* pointer to microcode */ +}; + +struct isdn_download_request { + int controller; /* controller number */ + int numprotos; /* number of protocols in 'protocols' */ + struct isdn_dr_prot *protocols; +}; + +#define I4B_CTRL_DOWNLOAD _IOW('4', 100, struct isdn_download_request) + +/*---------------------------------------------------------------------------* + * Generic diagnostic interface for active cards + *---------------------------------------------------------------------------*/ +struct isdn_diagnostic_request { + int controller; /* controller number */ + u_int32_t cmd; /* diagnostic command to execute */ + size_t in_param_len; /* length of additional input parameter */ + void *in_param; /* optional input parameter */ + size_t out_param_len; /* available output space */ + void *out_param; /* output data goes here */ +}; + +#define I4B_ACTIVE_DIAGNOSTIC _IOW('4', 102, struct isdn_diagnostic_request) + +#endif /* _I4B_IOCTL_H_ */ diff --git a/sys/i4b/include/i4b_isdnq931.h b/sys/i4b/include/i4b_isdnq931.h new file mode 100644 index 0000000..bdc77f0 --- /dev/null +++ b/sys/i4b/include/i4b_isdnq931.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isdnq931.h - DSS1 layer 3 message types + * ------------------------------------------- + * + * $Id: i4b_isdnq931.h,v 1.4 1998/12/05 18:02:54 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:04:01 1998] + * + *---------------------------------------------------------------------------*/ + +/* protocol discriminators */ + +#define PD_Q931 0x08 /* Q.931/I.451 */ + +/* Q.931 single octett information element identifiers */ + +#define IEI_SENDCOMPL 0xa1 /* sending complete */ + +/* Q.931 variable length information element identifiers */ + +#define IEI_SEGMMSG 0x00 /* segmented message */ +#define IEI_BEARERCAP 0x04 /* bearer capabilities */ +#define IEI_CAUSE 0x08 /* cause */ +#define IEI_CALLID 0x10 /* call identity */ +#define IEI_CALLSTATE 0x14 /* call state */ +#define IEI_CHANNELID 0x18 /* channel identification */ +#define IEI_PROGRESSI 0x1e /* progress indicator */ +#define IEI_NETSPCFAC 0x20 /* network specific facilities */ +#define IEI_NOTIFIND 0x27 /* notification indicator */ +#define IEI_DISPLAY 0x28 /* display */ +#define IEI_DATETIME 0x29 /* date/time */ +#define IEI_KEYPAD 0x2c /* keypad facility */ +#define IEI_SIGNAL 0x34 /* signal */ +#define IEI_INFRATE 0x40 /* information rate */ +#define IEI_ETETDEL 0x42 /* end to end transit delay */ +#define IEI_TDELSELIND 0x43 /* transit delay selection and indication */ +#define IEI_PLBPARMS 0x44 /* packet layer binary parameters */ +#define IEI_PLWSIZE 0x45 /* packet layer window size */ +#define IEI_PSIZE 0x46 /* packet size */ +#define IEI_CUG 0x47 /* closed user group */ +#define IEI_REVCHRGI 0x4a /* reverse charge indication */ +#define IEI_CALLINGPN 0x6c /* calling party number */ +#define IEI_CALLINGPS 0x6d /* calling party subaddress */ +#define IEI_CALLEDPN 0x70 /* called party number */ +#define IEI_CALLEDPS 0x71 /* called party subaddress */ +#define IEI_REDIRNO 0x74 /* redirecting number */ +#define IEI_TRNSEL 0x78 /* transit network selection */ +#define IEI_RESTARTI 0x79 /* restart indicator */ +#define IEI_LLCOMPAT 0x7c /* low layer compatibility */ +#define IEI_HLCOMPAT 0x7d /* high layer compatibility */ +#define IEI_USERUSER 0x7e /* user-user */ +#define IEI_ESACPE 0x7f /* escape for extension */ + +/* Q.932 variable length information element identifiers */ + +#define IEI_EXTFAC 0x0d /* extended facility */ +#define IEI_FACILITY 0x1c /* facility */ +#define IEI_INFOREQ 0x32 /* information request */ +#define IEI_FEATACT 0x38 /* feature activation */ +#define IEI_FEATIND 0x39 /* feature indication */ +#define IEI_SERVPID 0x3a /* service profile identification */ +#define IEI_ENDPTID 0x3b /* endpoint identifier */ + +/* Q.933 variable length information element identifiers */ + +#define IEI_DATALCID 0x19 /* data link connection identifier */ +#define IEI_LLCOREP 0x48 /* link layer core parameters */ +#define IEI_LLPROTP 0x49 /* link layer protocol parameters */ +#define IEI_X213PRI 0x50 /* X.213 priority */ +#define IEI_REPORTT 0x51 /* report type */ +#define IEI_LNKITYVERF 0x53 /* link integrity verification */ +#define IEI_PVCSTAT 0x57 /* PVC status */ + +/* Q.95x variable length information element identifiers */ + +#define IEI_PRECLEV 0x41 /* precedence level */ +#define IEI_CONCTDNO 0x4c /* connected number */ +#define IEI_CONCTDSA 0x4d /* connected subaddress */ +#define IEI_REDICNNO 0x76 /* redirection number */ + +/* single octett information elements */ + +#define SOIE_SHIFT 0x90 /* shift codeset */ +#define SHIFT_LOCK 0x08 /* shift codeset, locking shift bit */ +#define SOIE_MDSC 0xa0 /* more data AND/OR sending complete */ +#define SOIE_SENDC 0xa1 /* sending complete */ +#define SOIE_CONGL 0xb0 /* congestion level */ +#define SOIE_REPTI 0xd0 /* repeat indicator */ + +/* codesets */ + +#define CODESET_0 0 /* codeset 0, normal DSS1 codeset */ + +/* Q.931/Q.932 message types (see Q.931 03/93 p10 and p311) */ + +/* call establishment messages */ + +#define ALERT 0x01 +#define CALL_PROCEEDING 0x02 +#define PROGRESS 0x03 +#define SETUP 0x05 +#define CONNECT 0x07 +#define SETUP_ACKNOWLEDGE 0x0d +#define CONNECT_ACKNOWLEDGE 0x0f + +/* call information phase messages */ + +#define USER_INFORMATION 0x20 +#define SUSPEND_REJECT 0x21 +#define RESUME_REJECT 0x22 +#define HOLD 0x24 +#define SUSPEND 0x25 +#define RESUME 0x26 +#define HOLD_ACKNOWLEDGE 0x28 +#define SUSPEND_ACKNOWLEDGE 0x2d +#define RESUME_ACKNOWLEDGE 0x2e +#define HOLD_REJECT 0x30 +#define RETRIEVE 0x31 +#define RETRIEVE_ACKNOWLEDGE 0x32 +#define RETRIEVE_REJECT 0x37 + +/* call clearing */ + +#define DISCONNECT 0x45 +#define RESTART 0x46 +#define RELEASE 0x4d +#define RESTART_ACKNOWLEDGE 0x4e +#define RELEASE_COMPLETE 0x5a + +/* misc messages */ + +#define SEGMENT 0x60 +#define FACILITY 0x62 +#define REGISTER 0x64 +#define NOTIFY 0x6e +#define STATUS_ENQUIRY 0x75 +#define CONGESTION_CONTROL 0x79 +#define INFORMATION 0x7b +#define STATUS 0x7d + +/* EOF */ diff --git a/sys/i4b/include/i4b_l1l2.h b/sys/i4b/include/i4b_l1l2.h new file mode 100644 index 0000000..782ca68 --- /dev/null +++ b/sys/i4b/include/i4b_l1l2.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1l2.h - i4b layer 1 / layer 2 interactions + * --------------------------------------------------- + * + * $Id: i4b_l1l2.h,v 1.7 1998/12/05 18:02:56 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:04:25 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L1L2_H_ +#define _I4B_L1L2_H_ + +#ifdef __FreeBSD__ +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_trace.h> +#endif + +extern struct i4b_l1l2_func i4b_l1l2_func; + +struct i4b_l1l2_func +{ + /* Layer 1 --> Layer 2 */ + /* =================== */ + + int (*PH_DATA_IND) (int, struct mbuf *); + int (*PH_ACTIVATE_IND) (int); + int (*PH_DEACTIVATE_IND) (int); + +#define PH_Data_Ind(unit, data) \ + ((*i4b_l1l2_func.PH_DATA_IND)(unit, data)) +#define PH_Act_Ind(unit) \ + ((*i4b_l1l2_func.PH_ACTIVATE_IND)(unit)) +#define PH_Deact_Ind(unit) \ + ((*i4b_l1l2_func.PH_DEACTIVATE_IND)(unit)) + + + /* Layer 2 --> Layer 1 */ + /* =================== */ + + int (*PH_DATA_REQ) (int, struct mbuf *, int); + + /* 3rd ph_data_req parameter */ +#define MBUF_DONTFREE 0 +#define MBUF_FREE 1 + + int (*PH_ACTIVATE_REQ) (int); + +#define PH_Data_Req(unit, data, freeflag) \ + ((*i4b_l1l2_func.PH_DATA_REQ)(unit, data, freeflag)) +#define PH_Act_Req(unit) \ + ((*i4b_l1l2_func.PH_ACTIVATE_REQ)(unit)) + + /* Layer 1 --> upstream, ISDN trace data */ + /* ===================================== */ + int (*MPH_TRACE_IND) (i4b_trace_hdr_t *, int, unsigned char *); + +#define MPH_Trace_Ind(header, length, pointer) \ + ((*i4b_l1l2_func.MPH_TRACE_IND)(header, length, pointer)) + + /* L1/L2 management command and status information */ + /* =============================================== */ + int (*MPH_STATUS_IND) (int, int, int); + int (*MPH_COMMAND_REQ) (int, int, int); + +#define MPH_Status_Ind(unit, status, parm) \ + ((*i4b_l1l2_func.MPH_STATUS_IND)(unit, status, parm)) +#define MPH_Command_Req(unit, command, parm) \ + ((*i4b_l1l2_func.MPH_COMMAND_REQ)(unit, command, parm)) +}; + +#endif /* _I4B_L1L2_H_ */ + diff --git a/sys/i4b/include/i4b_l2l3.h b/sys/i4b/include/i4b_l2l3.h new file mode 100644 index 0000000..81ab182 --- /dev/null +++ b/sys/i4b/include/i4b_l2l3.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2l3.h - i4b layer 2 / layer 3 interactions + * ----------------------------------------------- + * + * $Id: i4b_l2l3.h,v 1.5 1998/12/05 18:02:57 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:04:44 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L2L3_H_ +#define _I4B_L2L3_H_ + +extern struct i4b_l2l3_func i4b_l2l3_func; + +struct i4b_l2l3_func +{ + /* Layer 2 --> Layer 3 */ + /* =================== */ + + int (*DL_ESTABLISH_IND) (int); + int (*DL_ESTABLISH_CNF) (int); + + int (*DL_RELEASE_IND) (int); + int (*DL_RELEASE_CNF) (int); + + int (*DL_DATA_IND) (int, struct mbuf *); + + int (*DL_UNIT_DATA_IND) (int, struct mbuf *); + +#define DL_Est_Ind(unit) \ + ((*i4b_l2l3_func.DL_ESTABLISH_IND)(unit)) +#define DL_Est_Cnf(unit) \ + ((*i4b_l2l3_func.DL_ESTABLISH_CNF)(unit)) +#define DL_Rel_Ind(unit) \ + ((*i4b_l2l3_func.DL_RELEASE_IND)(unit)) +#define DL_Rel_Cnf(unit) \ + ((*i4b_l2l3_func.DL_RELEASE_CNF)(unit)) +#define DL_Data_Ind(unit, data) \ + ((*i4b_l2l3_func.DL_DATA_IND)(unit, data)) +#define DL_Unit_Data_Ind(unit, data) \ + ((*i4b_l2l3_func.DL_UNIT_DATA_IND)(unit, data)) + +#define DL_Est_Ind_A \ + (i4b_l2l3_func.DL_ESTABLISH_IND) +#define DL_Est_Cnf_A \ + (i4b_l2l3_func.DL_ESTABLISH_CNF) +#define DL_Rel_Ind_A \ + (i4b_l2l3_func.DL_RELEASE_IND) +#define DL_Rel_Cnf_A \ + (i4b_l2l3_func.DL_RELEASE_CNF) + + /* Layer 3 --> Layer 2 */ + /* =================== */ + + int (*DL_ESTABLISH_REQ) (int); + + int (*DL_RELEASE_REQ) (int); + + int (*DL_DATA_REQ) (int, struct mbuf *); + + int (*DL_UNIT_DATA_REQ) (int, struct mbuf *); + +#define DL_Est_Req(unit) \ + ((*i4b_l2l3_func.DL_ESTABLISH_REQ)(unit)) +#define DL_Rel_Req(unit) \ + ((*i4b_l2l3_func.DL_RELEASE_REQ)(unit)) +#define DL_Data_Req(unit, data) \ + ((*i4b_l2l3_func.DL_DATA_REQ)(unit, data)) +#define DL_Unit_Data_Req(unit, data) \ + ((*i4b_l2l3_func.DL_UNIT_DATA_REQ)(unit, data)) + + /* Layer 2 --> Layer 3 management */ + /* ============================== */ + + int (*MDL_STATUS_IND) (int, int, int); /* L2 --> L3 status */ + +#define MDL_Status_Ind(unit, status, parm) \ + ((*i4b_l2l3_func.MDL_STATUS_IND)(unit, status, parm)) + + /* Layer 3 --> Layer 2 management */ + /* ============================== */ + + int (*MDL_COMMAND_REQ) (int, int, int); /* L3 --> L2 command */ + +#define MDL_Command_Req(unit, command, parm) \ + ((*i4b_l2l3_func.MDL_COMMAND_REQ)(unit, command, parm)) +}; + +#endif /* _I4B_L2L3_H_ */ + diff --git a/sys/i4b/include/i4b_l3l4.h b/sys/i4b/include/i4b_l3l4.h new file mode 100644 index 0000000..642777c --- /dev/null +++ b/sys/i4b/include/i4b_l3l4.h @@ -0,0 +1,260 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l3l4.h - layer 3 / layer 4 interface + * ------------------------------------------ + * + * $Id: i4b_l3l4.h,v 1.21 1998/12/05 18:02:59 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:04:58 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L3L4_H_ +#define _I4B_L3L4_H_ + +#define T303VAL (hz*4) /* 4 seconds timeout */ +#define T305VAL (hz*30) /* 30 seconds timeout */ +#define T308VAL (hz*4) /* 4 seconds timeout */ +#define T309VAL (hz*90) /* 90 seconds timeout */ +#define T310VAL (hz*60) /* 30-120 seconds timeout */ +#define T313VAL (hz*4) /* 4 seconds timeout */ +#define T400DEF (hz*10) /* 10 seconds timeout */ + +#define N_CALL_DESC (MAX_CONTROLLERS*2) /* no of call descriptors */ + +extern int nctrl; /* number of controllers detected in system */ + +typedef struct bchan_statistics { + int outbytes; + int inbytes; +} bchan_statistics_t; + +/*---------------------------------------------------------------------------* + * table of things the driver needs to know about the b channel + * it is connected to for data transfer + *---------------------------------------------------------------------------*/ +typedef struct i4l_isdn_bchan_linktab { + int unit; + int channel; + void (*bch_config)(int unit, int channel, int bprot, int updown); + void (*bch_tx_start)(int unit, int channel); + void (*bch_stat)(int unit, int channel, bchan_statistics_t *bsp); + struct ifqueue *tx_queue; + struct ifqueue *rx_queue; /* data xfer for NON-HDLC traffic */ + struct mbuf **rx_mbuf; /* data xfer for HDLC based traffic */ +} isdn_link_t; + +/*---------------------------------------------------------------------------* + * table of things the b channel handler needs to know about + * the driver it is connected to for data transfer + *---------------------------------------------------------------------------*/ +typedef struct i4l_driver_bchan_linktab { + int unit; + void (*bch_rx_data_ready)(int unit); + void (*bch_tx_queue_empty)(int unit); + void (*bch_activity)(int unit, int rxtx); +#define ACT_RX 0 +#define ACT_TX 1 + void (*line_connected)(int unit, void *cde); + void (*line_disconnected)(int unit, void *cde); + void (*dial_response)(int unit, int stat); + void (*updown_ind)(int unit, int updown); +} drvr_link_t; + +/* global linktab functions for controller types (aka hardware drivers) */ +struct ctrl_type_desc { + isdn_link_t* (*get_linktab)(int unit, int channel); + void (*set_linktab)(int unit, int channel, drvr_link_t *dlt); +}; +extern struct ctrl_type_desc ctrl_types[]; + +/* global linktab functions for RBCH userland driver */ + +drvr_link_t *rbch_ret_linktab(int unit); +void rbch_set_linktab(int unit, isdn_link_t *ilt); + +/* global linktab functions for IPR network driver */ + +drvr_link_t *ipr_ret_linktab(int unit); +void ipr_set_linktab(int unit, isdn_link_t *ilt); + +/* global linktab functions for TEL userland driver */ + +drvr_link_t *tel_ret_linktab(int unit); +void tel_set_linktab(int unit, isdn_link_t *ilt); + +/* global linktab functions for ISPPP userland driver */ + +drvr_link_t *i4bisppp_ret_linktab(int unit); +void i4bisppp_set_linktab(int unit, isdn_link_t *ilt); + +/*---------------------------------------------------------------------------* + * this structure describes one call/connection on one B-channel + * and all its parameters + *---------------------------------------------------------------------------*/ +typedef struct +{ + u_int cdid; /* call descriptor id */ + int controller; /* isdn controller number */ + int cr; /* call reference value */ + + int crflag; /* call reference flag */ +#define CRF_ORIG 0 /* originating side */ +#define CRF_DEST 1 /* destinating side */ + + int channelid; /* channel id value */ + int channelexcl; /* channel exclusive */ + + int bprot; /* B channel protocol BPROT_XXX */ + + int driver; /* driver to use for B channel */ + int driver_unit; /* unit for above driver number */ + + cause_t cause_in; /* cause value from NT */ + cause_t cause_out; /* cause value to NT */ + + int call_state; /* from incoming SETUP */ + + u_char dst_telno[TELNO_MAX]; /* destination number */ + u_char src_telno[TELNO_MAX]; /* source number */ + int scr_ind; /* screening ind for incoming call */ + + int Q931state; /* Q.931 state for call */ + int event; /* event to be processed */ + + int response; /* setup response type */ + + int T303; /* SETUP sent response timeout */ + int T303_first_to; /* first timeout flag */ + + int T305; /* DISC without PROG IND */ + + int T308; /* RELEASE sent response timeout*/ + int T308_first_to; /* first timeout flag */ + + int T309; /* data link disconnect timeout */ + + int T310; /* CALL PROC received */ + + int T313; /* CONNECT sent timeout */ + + int T400; /* L4 timeout */ + + isdn_link_t *ilt; /* isdn B channel linktab */ + drvr_link_t *dlt; /* driver linktab */ + + int dir; /* outgoing or incoming call */ +#define DIR_OUTGOING 0 +#define DIR_INCOMING 1 + + int timeout_active; /* idle timeout() active flag */ + +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300001) || \ + (!defined(__FreeBSD_version) && defined(__FreeBSD__) && __FreeBSD__ >= 3) + struct callout_handle idle_timeout_handle; + struct callout_handle T303_callout; + struct callout_handle T305_callout; + struct callout_handle T308_callout; + struct callout_handle T309_callout; + struct callout_handle T310_callout; + struct callout_handle T313_callout; + struct callout_handle T400_callout; + int callouts_inited; /* must init before use */ +#endif + + int idletime_state; /* wait for idle_time begin */ +#define IST_IDLE 0 /* shorthold mode disabled */ +#define IST_NONCHK 1 /* in non-checked window */ +#define IST_CHECK 2 /* in idle check window */ +#define IST_SAFE 3 /* in safety zone */ + + time_t idletimechk_start; /* check idletime window start */ + time_t connect_time; /* time connect was made */ + time_t last_active_time; /* last time with activity */ + + /* for incoming connections: */ + time_t max_idle_time; /* max time without activity */ + + /* for outgoing connections: */ + time_t unitlen_time; /* length of a charging unit */ + time_t idle_time; /* idle time before end of unit */ + time_t earlyhup_time; /* safety time zone at end of unit */ + + int aocd_flag; /* AOCD used for unitlength calc*/ + time_t last_aocd_time; /* last time AOCD received */ + int units; /* number of AOCD charging units*/ + int units_type; /* units type: AOCD, AOCE */ + int cunits; /* calculated units */ + + int isdntxdelay; /* isdn tx delay after connect */ + + u_char display[DISPLAY_MAX]; /* display information element */ + char datetime[DATETIME_MAX]; /* date/time information element*/ +} call_desc_t; + +extern call_desc_t call_desc[N_CALL_DESC]; + +/* forward decl. */ +struct isdn_diagnostic_request; +struct isdn_dr_prot; + +/*---------------------------------------------------------------------------* + * this structure "describes" one controller + *---------------------------------------------------------------------------*/ +typedef struct +{ + int unit; /* unit number of this contr. */ + int ctrl_type; /* controller type (CTRL_XXX) */ + int card_type; /* card manufacturer (CARD_XXX) */ + + int dl_est; /* layer 2 established */ +#define DL_DOWN 0 +#define DL_UP 1 + + int bch_state[2]; /* states of the b channels */ +#define BCH_ST_FREE 0 /* free to be used, idle */ +#define BCH_ST_RSVD 1 /* reserved, may become free or used */ +#define BCH_ST_USED 2 /* in use for data transfer */ + + int tei; /* current tei or -1 if invalid */ + + /* pointers to functions to be called from L4 */ + + void (*N_CONNECT_REQUEST) (unsigned int); + void (*N_CONNECT_RESPONSE) (unsigned int, int, int); + void (*N_DISCONNECT_REQUEST) (unsigned int, int); + void (*N_ALERT_REQUEST) (unsigned int); + void (*N_SET_TRACE) (int unit, int val); + int (*N_GET_TRACE) (int unit); + int (*N_DOWNLOAD) (int unit, int numprotos, struct isdn_dr_prot *protocols); + int (*N_DIAGNOSTICS) (int unit, struct isdn_diagnostic_request*); + void (*N_MGMT_COMMAND) (int unit, int cmd, int parm); +} ctrl_desc_t; + +extern ctrl_desc_t ctrl_desc[MAX_CONTROLLERS]; + +#endif /* _I4B_Q931_H_ */ diff --git a/sys/i4b/include/i4b_mbuf.h b/sys/i4b/include/i4b_mbuf.h new file mode 100644 index 0000000..49ee26d --- /dev/null +++ b/sys/i4b/include/i4b_mbuf.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b - mbuf handling support routines + * -------------------------------------- + * + * $Id: i4b_mbuf.h,v 1.6 1998/12/05 18:03:00 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:05:12 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_MBUF_H_ +#define _I4B_MBUF_H_ + +#define IF_QEMPTY(ifq) ((ifq)->ifq_len == 0) + +struct mbuf *i4b_Dgetmbuf( int ); +void i4b_Dfreembuf( struct mbuf *m ); +void i4b_Dcleanifq( struct ifqueue * ); + +struct mbuf *i4b_Bgetmbuf( int ); +void i4b_Bfreembuf( struct mbuf *m ); +void i4b_Bcleanifq( struct ifqueue * ); + +#endif /* _I4B_MBUF_H_ */ + +/* EOF */ diff --git a/sys/i4b/include/i4b_tel_ioctl.h b/sys/i4b/include/i4b_tel_ioctl.h new file mode 100644 index 0000000..b7f0f73 --- /dev/null +++ b/sys/i4b/include/i4b_tel_ioctl.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tel_ioctl.h telephony interface ioctls + * ------------------------------------------ + * + * $Id: i4b_tel_ioctl.h,v 1.5 1998/12/14 10:31:58 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:37:36 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_TEL_IOCTL_H_ +#define _I4B_TEL_IOCTL_H_ + +/* supported audio format conversions for /dev/i4btelXX devices */ + +#define CVT_NONE 0 /* no format conversion */ +#define CVT_ALAW2ULAW 1 /* kernel A-law, userland mu-law */ + +/*---------------------------------------------------------------------------* + * get / set audio format + *---------------------------------------------------------------------------*/ + +#define I4B_TEL_GETAUDIOFMT _IOR('A', 0, int) +#define I4B_TEL_SETAUDIOFMT _IOW('A', 1, int) +#define I4B_TEL_EMPTYINPUTQUEUE _IOW('A', 2, int) + +#endif /* _I4B_TEL_IOCTL_H_ */ diff --git a/sys/i4b/include/i4b_trace.h b/sys/i4b/include/i4b_trace.h new file mode 100644 index 0000000..07e08da --- /dev/null +++ b/sys/i4b/include/i4b_trace.h @@ -0,0 +1,91 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_trace.h - header file for trace data read device + * ---------------------------------------------------- + * + * $Id: i4b_trace.h,v 1.5 1998/12/05 18:06:01 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:37:49 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_TRACE_H_ +#define _I4B_TRACE_H_ + +/*---------------------------------------------------------------------------* + * structure of the header at the beginning of every trace mbuf + *---------------------------------------------------------------------------*/ +typedef struct { + int length; /* length of the following mbuf */ + int unit; /* controller unit number */ + int type; /* type of channel */ +#define TRC_CH_I 0 /* Layer 1 INFO's */ +#define TRC_CH_D 1 /* D channel */ +#define TRC_CH_B1 2 /* B1 channel */ +#define TRC_CH_B2 3 /* B2 channel */ + int dir; /* direction */ +#define FROM_TE 0 /* user -> network */ +#define FROM_NT 1 /* network -> user */ + int trunc; /* # of truncated bytes (frame > MCLBYTES) */ + unsigned int count; /* frame count for this unit/type */ + struct timeval time; /* timestamp for this frame */ +} i4b_trace_hdr_t; + +#define INFO0 0 /* layer 1 */ +#define INFO1_8 1 +#define INFO1_10 2 +#define INFO2 3 +#define INFO3 4 +#define INFO4_8 5 +#define INFO4_10 6 + +/*---------------------------------------------------------------------------* + * ioctl via /dev/i4btrc device(s): + * get/set current trace flag settings + *---------------------------------------------------------------------------*/ + +#define I4B_TRC_GET _IOR('T', 0, int) /* get trace settings */ +#define I4B_TRC_SET _IOW('T', 1, int) /* set trace settings */ + +#define TRACE_OFF 0x00 /* tracing off */ +#define TRACE_I 0x01 /* trace L1 INFO's on */ +#define TRACE_D_TX 0x02 /* trace D channel on */ +#define TRACE_D_RX 0x04 /* trace D channel on */ +#define TRACE_B_TX 0x08 /* trace B channel on */ +#define TRACE_B_RX 0x10 /* trace B channel on */ + +typedef struct { + int rxunit; /* unit # for rx frames */ + int rxflags; /* d and/or b channel */ + int txunit; /* unit # for tx frames */ + int txflags; /* d and/or b channel */ +} i4b_trace_setupa_t; + +#define I4B_TRC_SETA _IOW('T', 2, i4b_trace_setupa_t) /* set analyze mode */ +#define I4B_TRC_RESETA _IOW('T', 3, int) /* reset analyze mode */ + +#endif /* _I4B_TRACE_H_ */ diff --git a/sys/i4b/layer1/i4b_avm_a1.c b/sys/i4b/layer1/i4b_avm_a1.c new file mode 100644 index 0000000..bb55979 --- /dev/null +++ b/sys/i4b/layer1/i4b_avm_a1.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 1996 Andrew Gordon. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_avm_a1.c - AVM A1/Fritz passive card driver for isdn4bsd + * ------------------------------------------------------------ + * + * $Id: i4b_avm_a1.c,v 1.20 1998/12/16 13:57:21 hm Exp $ + * + * last edit-date: [Wed Dec 16 14:59:59 1998] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(AVM_A1) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#ifndef __FreeBSD__ +static u_int8_t avma1_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void avma1_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void avma1_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void avma1_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * AVM A1 and AVM Fritz! Card special registers + *---------------------------------------------------------------------------*/ + +#define AVM_CONF_REG 0x1800 /* base offset for config register */ +#define AVM_CONF_IRQ 0x1801 /* base offset for IRQ register */ + /* config register write */ +#define AVM_CONF_WR_RESET 0x01 /* 1 = RESET ISAC and HSCX */ +#define AVM_CONF_WR_CCL 0x02 /* 1 = clear counter low nibble */ +#define AVM_CONF_WR_CCH 0x04 /* 1 = clear counter high nibble */ +#define AVM_CONF_WR_IRQEN 0x08 /* 1 = enable IRQ */ +#define AVM_CONF_WR_TEST 0x10 /* test bit */ + /* config register read */ +#define AVM_CONF_RD_IIRQ 0x01 /* 0 = ISAC IRQ active */ +#define AVM_CONF_RD_HIRQ 0x02 /* 0 = HSCX IRQ active */ +#define AVM_CONF_RD_CIRQ 0x04 /* 0 = counter IRQ active */ +#define AVM_CONF_RD_ZER1 0x08 /* unused, always read 0 */ +#define AVM_CONF_RD_TEST 0x10 /* test bit read back */ +#define AVM_CONF_RD_ZER2 0x20 /* unused, always read 0 */ + +/*---------------------------------------------------------------------------* + * AVM read fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +avma1_read_fifo(void *buf, const void *base, size_t len) +{ + insb((int)base - 0x3e0, (u_char *)buf, (u_int)len); +} +#else +static void +avma1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+4].t; + bus_space_handle_t h = sc->sc_maps[what+4].h; + bus_space_read_multi_1(t, h, 0, buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM write fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +avma1_write_fifo(void *base, const void *buf, size_t len) +{ + outsb((int)base - 0x3e0, (u_char *)buf, (u_int)len); +} +#else +static void +avma1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+4].t; + bus_space_handle_t h = sc->sc_maps[what+4].h; + bus_space_write_multi_1(t, h, 0, (u_int8_t*)buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM write register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +avma1_write_reg(u_char *base, u_int offset, u_int v) +{ + outb((int)base + offset, (u_char)v); +} +#else +static void +avma1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_space_write_1(t, h, offs, data); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM read register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static u_char +avma1_read_reg(u_char *base, u_int offset) +{ + return (inb((int)base + offset)); +} +#else +static u_int8_t +avma1_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + return bus_space_read_1(t, h, offs); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_avma1 - probe for AVM A1 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_avma1(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + u_char savebyte; + u_char byte; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for AVM A1/Fritz!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq)-1) + { + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for AVM A1/Fritz!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for AVM A1/Fritz!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + + dev->id_msize = 0; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0x200: + case 0x240: + case 0x300: + case 0x340: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for AVM A1/Fritz!\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + sc->clearirq = NULL; + sc->readreg = avma1_read_reg; + sc->writereg = avma1_write_reg; + + sc->readfifo = avma1_read_fifo; + sc->writefifo = avma1_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_AVMA1; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t)dev->id_iobase + 0x1400 - 0x20; + + HSCX_A_BASE = (caddr_t)dev->id_iobase + 0x400 - 0x20; + HSCX_B_BASE = (caddr_t)dev->id_iobase + 0xc00 - 0x20; + + /* + * Read HSCX A/B VSTR. + * Expected value for AVM A1 is 0x04 or 0x05 and for the + * AVM Fritz!Card is 0x05 in the least significant bits. + */ + + if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) || + (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) ) + { + printf("isic%d: HSCX VSTR test failed for AVM A1/Fritz\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + /* AVM A1 or Fritz! control register bits: */ + /* read write */ + /* 0x01 hscx irq* RESET */ + /* 0x02 isac irq* clear counter1 */ + /* 0x04 counter irq* clear counter2 */ + /* 0x08 always 0 irq enable */ + /* 0x10 read test bit set test bit */ + /* 0x20 always 0 unused */ + + /* + * XXX the following test may be destructive, to prevent the + * worst case, we save the byte first, and in case the test + * fails, we write back the saved byte ..... + */ + + savebyte = inb(dev->id_iobase + AVM_CONF_REG); + + /* write low to test bit */ + + outb(dev->id_iobase + AVM_CONF_REG, 0x00); + + /* test bit and next higher and lower bit must be 0 */ + + if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x00) + { + printf("isic%d: Error, probe-1 failed, 0x%02x should be 0x00 for AVM A1/Fritz!\n", + dev->id_unit, byte); + outb(dev->id_iobase + AVM_CONF_REG, savebyte); + return (0); + } + + /* write high to test bit */ + + outb(dev->id_iobase + AVM_CONF_REG, 0x10); + + /* test bit must be high, next higher and lower bit must be 0 */ + + if((byte = inb(dev->id_iobase + AVM_CONF_REG) & 0x38) != 0x10) + { + printf("isic%d: Error, probe-2 failed, 0x%02x should be 0x10 for AVM A1/Fritz!\n", + dev->id_unit, byte); + outb(dev->id_iobase + AVM_CONF_REG, savebyte); + return (0); + } + + return (1); +} + +#else + +int +isic_probe_avma1(struct isic_attach_args *ia) +{ + u_int8_t savebyte, v1, v2; + + /* + * Read HSCX A/B VSTR. + * Expected value for AVM A1 is 0x04 or 0x05 and for the + * AVM Fritz!Card is 0x05 in the least significant bits. + */ + + v1 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXA+1].t, ia->ia_maps[ISIC_WHAT_HSCXA+1].h, H_VSTR) & 0x0f; + v2 = bus_space_read_1(ia->ia_maps[ISIC_WHAT_HSCXB+1].t, ia->ia_maps[ISIC_WHAT_HSCXB+1].h, H_VSTR) & 0x0f; + if (v1 != v2 || (v1 != 0x05 && v1 != 0x04)) + return 0; + + /* AVM A1 or Fritz! control register bits: */ + /* read write */ + /* 0x01 hscx irq* RESET */ + /* 0x02 isac irq* clear counter1 */ + /* 0x04 counter irq* clear counter2 */ + /* 0x08 always 0 irq enable */ + /* 0x10 read test bit set test bit */ + /* 0x20 always 0 unused */ + + /* + * XXX the following test may be destructive, to prevent the + * worst case, we save the byte first, and in case the test + * fails, we write back the saved byte ..... + */ + + savebyte = bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0); + + /* write low to test bit */ + + bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0); + + /* test bit and next higher and lower bit must be 0 */ + + if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x00) + { + bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte); + return 0; + } + + /* write high to test bit */ + + bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, 0x10); + + /* test bit must be high, next higher and lower bit must be 0 */ + + if((bus_space_read_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0) & 0x38) != 0x10) + { + bus_space_write_1(ia->ia_maps[0].t, ia->ia_maps[0].h, 0, savebyte); + return 0; + } + + return (1); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_avma1 - attach AVM A1 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_attach_avma1(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* reset the HSCX and ISAC chips */ + + outb(dev->id_iobase + AVM_CONF_REG, 0x00); + DELAY(SEC_DELAY / 10); + + outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_RESET); + DELAY(SEC_DELAY / 10); + + outb(dev->id_iobase + AVM_CONF_REG, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + outb(dev->id_iobase + AVM_CONF_IRQ, (ffs(sc->sc_irq)) - 1); + DELAY(SEC_DELAY / 10); + + /* enable IRQ, disable counter IRQ */ + + outb(dev->id_iobase + AVM_CONF_REG, AVM_CONF_WR_IRQEN | + AVM_CONF_WR_CCH | AVM_CONF_WR_CCL); + DELAY(SEC_DELAY / 10); + + return (1); +} + +#else + +int +isic_attach_avma1(struct isic_softc *sc) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + + sc->clearirq = NULL; + sc->readreg = avma1_read_reg; + sc->writereg = avma1_write_reg; + + sc->readfifo = avma1_read_fifo; + sc->writefifo = avma1_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_AVMA1; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* reset the HSCX and ISAC chips */ + + bus_space_write_1(t, h, 0, 0x00); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0, AVM_CONF_WR_RESET); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + bus_space_write_1(t, h, 1, sc->sc_irq); + DELAY(SEC_DELAY / 10); + + /* enable IRQ, disable counter IRQ */ + + bus_space_write_1(t, h, 0, AVM_CONF_WR_IRQEN | + AVM_CONF_WR_CCH | AVM_CONF_WR_CCL); + DELAY(SEC_DELAY / 10); + + return (1); +} +#endif + +#endif /* ISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c new file mode 100644 index 0000000..483eb66 --- /dev/null +++ b/sys/i4b/layer1/i4b_avm_fritz_pcmcia.c @@ -0,0 +1,504 @@ +/* + * Copyright (c) 1998 Matthias Apitz. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * Fritz!Card pcmcia specific routines for isic driver + * --------------------------------------------------- + * + * $Id: i4b_avm_fritz_pcmcia.c,v 1.7 1998/12/01 21:25:53 hm Exp $ + * + * last edit-date: [Tue Dec 1 22:03:51 1998] + * + * -ap added support for AVM PCMCIA Fritz!Card + * -mh split into separate file + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif + +#if NISIC > 0 && defined(AVM_PCMCIA) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/layer1/pcmcia_isic.h> + +#ifndef __FreeBSD__ +/* PCMCIA support routines */ +static u_int8_t avma1_pcmcia_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void avma1_pcmcia_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void avma1_pcmcia_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void avma1_pcmcia_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * AVM PCMCIA Fritz!Card special registers + *---------------------------------------------------------------------------*/ + +/* + * register offsets from i/o base 0x140 or 0x300 + */ +#define ADDR_REG_OFFSET 0x02 +#define DATA_REG_OFFSET 0x03 +#define STAT0_OFFSET 0x04 +#define STAT1_OFFSET 0x05 +#define MODREG_OFFSET 0x06 +#define VERREG_OFFSET 0x07 +/* + * AVM PCMCIA Status Latch 0 read only bits + */ +#define ASL_IRQ_TIMER 0x10 /* Timer interrupt, active low */ +#define ASL_IRQ_ISAC 0x20 /* ISAC interrupt, active low */ +#define ASL_IRQ_HSCX 0x40 /* HSX interrupt, active low */ +#define ASL_IRQ_BCHAN ASL_IRQ_HSCX +#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER) +/* + * AVM Status Latch 0 write only bits + */ +#define ASL_RESET_ALL 0x01 /* reset siemens IC's, active 1 */ +#define ASL_TIMERDISABLE 0x02 /* active high */ +#define ASL_TIMERRESET 0x04 /* active high */ +#define ASL_ENABLE_INT 0x08 /* active high */ +/* + * AVM Status Latch 1 write only bits + */ +#define ASL1_LED0 0x10 /* active high */ +#define ASL1_LED1 0x20 /* active high */ + +#define ASL1_ENABLE_S0 0xc0 /* enable active S0 I/F */ + +/*----- EEpromless controller -----*/ +/* + * AVM Status Latch read/write bit + */ + +#define ASL_TESTBIT 0x80 + + +/*---------------------------------------------------------------------------* + * AVM read fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */ +static void +avma1_pcmcia_read_fifo(void *buf, const void *base, size_t len) +{ + outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20); + insb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len); +} +#else +/* offsets of the different 'what' arguments */ +static u_int8_t what_map[] = { + 0x20-0x20, /* ISIC_WHAT_ISAC */ + 0xA0-0x20, /* ISIC_WHAT_HSCXA */ + 0xE0-0x20 /* ISIC_WHAT_HSCXB */ +}; +static void +avma1_pcmcia_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]); + bus_space_read_multi_1(t, h, DATA_REG_OFFSET, buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM write fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +avma1_pcmcia_write_fifo(void *base, const void *buf, size_t len) +{ + outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base - 0x20); + outsb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char *)buf, (u_int)len); +} +#else +static void +avma1_pcmcia_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]); + bus_space_write_multi_1(t, h, DATA_REG_OFFSET, (u_int8_t*)buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM write register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +avma1_pcmcia_write_reg(u_char *base, u_int offset, u_int v) +{ + /* offset includes 0x20 FIFO ! */ + outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20); + outb(PCMCIA_IO_BASE + DATA_REG_OFFSET, (u_char)v); +} +#else +static void +avma1_pcmcia_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs); + bus_space_write_1(t, h, DATA_REG_OFFSET, data); +} +#endif + +/*---------------------------------------------------------------------------* + * AVM read register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static u_char +avma1_pcmcia_read_reg(u_char *base, u_int offset) +{ + /* offset includes 0x20 FIFO ! */ + outb(PCMCIA_IO_BASE + ADDR_REG_OFFSET, (int)base+offset-0x20); + return (inb(PCMCIA_IO_BASE + DATA_REG_OFFSET)); +} +#else +static u_int8_t +avma1_pcmcia_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, ADDR_REG_OFFSET, what_map[what]+offs); + return bus_space_read_1(t, h, DATA_REG_OFFSET); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_avma1_pcmcia - probe for AVM PCMCIA Fritz!Card + * This is in the bus attachemnt part on NetBSD (pcmcia_isic.c), no + * card specicfic probe is needed on direct config buses like pcmcia. + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_avma1_pcmcia(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + u_char byte; + int i; + u_int cardinfo; + + /* check max unit range */ + + if(dev->id_unit > 1) + { + printf("isic%d: Error, unit %d > MAXUNIT for AVM PCMCIA Fritz!Card\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* + * we trust the IRQ we got from PCCARD service + */ + sc->sc_irq = dev->id_irq; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0x140: + case 0x300: + break; + default: + printf("isic%d: Error, invalid iobase 0x%x specified for AVM PCMCIA Fritz!Card.\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + /* ResetController */ + + outb(dev->id_iobase + STAT0_OFFSET, 0x00); + DELAY(SEC_DELAY / 20); + outb(dev->id_iobase + STAT0_OFFSET, 0x01); + DELAY(SEC_DELAY / 20); + outb(dev->id_iobase + STAT0_OFFSET, 0x00); + + /* + * CheckController + * The logic to check for the PCMCIA was adapted as + * described by AVM. + */ + + outb(dev->id_iobase + ADDR_REG_OFFSET, 0x21); /* ISAC STAR */ + if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 ) + { + printf("isic%d: Error, ISAC STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n", + dev->id_unit, byte); + return(0); + } + + outb(dev->id_iobase + ADDR_REG_OFFSET, 0xa1); /* HSCX STAR */ + if ( (byte=inb(dev->id_iobase + DATA_REG_OFFSET) & 0xfd) != 0x48 ) + { + printf("isic%d: Error, HSCX STAR for AVM PCMCIA is 0x%0x (should be 0x48)\n", + dev->id_unit, byte); + return(0); + } + + byte = ASL_TESTBIT; + for (i=0; i<256; i++) { + byte = byte ? 0 : ASL_TESTBIT; + outb(dev->id_iobase + STAT0_OFFSET, byte); + if ((inb(dev->id_iobase+STAT0_OFFSET)&ASL_TESTBIT)!=byte) { + printf("isic%d: Error during toggle of AVM PCMCIA Status Latch0\n", + dev->id_unit); + return(0); + } + } + + sc->clearirq = NULL; + sc->readreg = avma1_pcmcia_read_reg; + sc->writereg = avma1_pcmcia_write_reg; + + sc->readfifo = avma1_pcmcia_read_fifo; + sc->writefifo = avma1_pcmcia_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_PCFRITZ; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; /* ap: XXX ??? */ + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + /* + * NOTE: for PCMCIA these are no real addrs; they are + * offsets to be written into the base+ADDR_REG_OFFSET register + * to pick up the values of the bytes fro base+DATA_REG_OFFSET + * + * see also the logic in the avma1_pcmcia_* routines; + * therefore we also must have the base addr in some static + * space or struct; XXX better solution? + */ + + PCMCIA_IO_BASE = dev->id_iobase; + ISAC_BASE = (caddr_t)0x20; + + HSCX_A_BASE = (caddr_t)0xA0; + HSCX_B_BASE = (caddr_t)0xE0; + + /* + * Read HSCX A/B VSTR. + * Expected value for AVM A1 is 0x04 or 0x05 and for the + * AVM Fritz!Card is 0x05 in the least significant bits. + */ + + if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) || + (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) ) + { + printf("isic%d: HSCX VSTR test failed for AVM PCMCIA Fritz!Card\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: 0x%0x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: 0x%0x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + /* + * seems we really have an AVM PCMCIA Fritz!Card controller + */ + cardinfo = inb(dev->id_iobase + VERREG_OFFSET)<<8 | inb(dev->id_iobase + MODREG_OFFSET); + printf("isic%d: successfully detect AVM PCMCIA cardinfo = 0x%0x\n", + dev->id_unit, cardinfo); + dev->id_flags = FLAG_AVM_A1_PCMCIA; + return (1); +} +#endif /* __FreeBSD__ */ + + + +/*---------------------------------------------------------------------------* + * isic_attach_fritzpcmcia - attach Fritz!Card + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_attach_fritzpcmica(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* ResetController again just to make sure... */ + + outb(dev->id_iobase + STAT0_OFFSET, 0x00); + DELAY(SEC_DELAY / 10); + outb(dev->id_iobase + STAT0_OFFSET, 0x01); + DELAY(SEC_DELAY / 10); + outb(dev->id_iobase + STAT0_OFFSET, 0x00); + DELAY(SEC_DELAY / 10); + + /* enable IRQ, disable counter IRQ */ + + outb(dev->id_iobase + STAT0_OFFSET, ASL_TIMERDISABLE | + ASL_TIMERRESET | ASL_ENABLE_INT); + /* DELAY(SEC_DELAY / 10); */ + + return(1); +} + +#else + +/* + * XXX - one time only! Some of this has to go into an enable + * function, with apropriate counterpart in disable, so a card + * could be removed an inserted again. But never mind for now, + * this won't work anyway for several reasons (both in NetBSD + * and in I4B). + */ +int +isic_attach_fritzpcmcia(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa) +{ + struct isic_softc *sc = &psc->sc_isic; + bus_space_tag_t t; + bus_space_handle_t h; + + /* Validate config info */ + if (cfe->num_memspace != 0) + printf(": unexpected number of memory spaces %d should be 0\n", + cfe->num_memspace); + if (cfe->num_iospace != 1) + printf(": unexpected number of memory spaces %d should be 1\n", + cfe->num_iospace); + + /* Allocate pcmcia space - exactly as dictated by the card */ + if (pcmcia_io_alloc(pa->pf, cfe->iospace[0].start, cfe->iospace[0].length, + 0, &psc->sc_pcioh)) + printf(": can't allocate i/o space\n"); + + /* map them */ + if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ? + PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, + cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) { + printf(": can't map i/o space\n"); + return 0; + } + + /* Setup bus space maps */ + sc->sc_num_mappings = 1; + sc->sc_cardtyp = CARD_TYPEP_PCFRITZ; + MALLOC_MAPS(sc); + + /* Copy our handles/tags to the MI maps */ + sc->sc_maps[0].t = psc->sc_pcioh.iot; + sc->sc_maps[0].h = psc->sc_pcioh.ioh; + sc->sc_maps[0].offset = 0; + sc->sc_maps[0].size = 0; /* not our mapping */ + + t = sc->sc_maps[0].t; + h = sc->sc_maps[0].h; + + sc->clearirq = NULL; + sc->readreg = avma1_pcmcia_read_reg; + sc->writereg = avma1_pcmcia_write_reg; + + sc->readfifo = avma1_pcmcia_read_fifo; + sc->writefifo = avma1_pcmcia_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_PCFRITZ; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* Reset controller again just to make sure... */ + + bus_space_write_1(t, h, STAT0_OFFSET, 0x00); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, STAT0_OFFSET, 0x01); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, STAT0_OFFSET, 0x00); + DELAY(SEC_DELAY / 10); + + /* enable IRQ, disable counter IRQ */ + + bus_space_write_1(t, h, STAT0_OFFSET, ASL_TIMERDISABLE | + ASL_TIMERRESET | ASL_ENABLE_INT); + + return 1; +} +#endif + +#endif /* NISIC > 0 && defined(AVM_PCMCIA) */ diff --git a/sys/i4b/layer1/i4b_bchan.c b/sys/i4b/layer1/i4b_bchan.c new file mode 100644 index 0000000..17ee273 --- /dev/null +++ b/sys/i4b/layer1/i4b_bchan.c @@ -0,0 +1,484 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_bchan.c - B channel handling L1 procedures + * ---------------------------------------------- + * + * $Id: i4b_bchan.c,v 1.28 1998/12/05 18:04:28 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:21:57 1998] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#else +#define NISIC 1 +#endif + +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <machine/stdarg.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#ifdef __FreeBSD__ +static void isic_bchannel_start(int unit, int h_chan); +static void isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp); +#else +static void isic_bchannel_start __P((int unit, int h_chan)); +static void isic_bchannel_stat __P((int unit, int h_chan, bchan_statistics_t *bsp)); +#endif + +static void isic_set_linktab(int unit, int channel, drvr_link_t *dlt); +static isdn_link_t *isic_ret_linktab(int unit, int channel); + +/*---------------------------------------------------------------------------* + * initialize one B channels rx/tx data structures and init/deinit HSCX + *---------------------------------------------------------------------------*/ +void +isic_bchannel_setup(int unit, int h_chan, int bprot, int activate) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + + int s = SPLI4B(); + + if(activate == 0) + { + /* deactivation */ + isic_hscx_init(sc, h_chan, activate); + } + + DBGL1(L1_BCHAN, "isic_bchannel_setup", ("unit=%d, channel=%d, %s\n", + sc->sc_unit, h_chan, activate ? "activate" : "deactivate")); + + /* general part */ + + chan->unit = sc->sc_unit; /* unit number */ + chan->channel = h_chan; /* B channel */ + chan->bprot = bprot; /* B channel protocol */ + chan->state = HSCX_IDLE; /* B channel state */ + + /* receiver part */ + + i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */ + + chan->rx_queue.ifq_maxlen = IFQ_MAXLEN; + + chan->rxcount = 0; /* reset rx counter */ + + i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */ + + chan->in_mbuf = NULL; /* reset mbuf ptr */ + chan->in_cbptr = NULL; /* reset mbuf curr ptr */ + chan->in_len = 0; /* reset mbuf data len */ + + /* transmitter part */ + + i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */ + + chan->tx_queue.ifq_maxlen = IFQ_MAXLEN; + + chan->txcount = 0; /* reset tx counter */ + + i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */ + + chan->out_mbuf_head = NULL; /* reset head mbuf ptr */ + chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */ + chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */ + chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */ + + if(activate != 0) + { + /* activation */ + isic_hscx_init(sc, h_chan, activate); + } + + splx(s); +} + +/*---------------------------------------------------------------------------* + * start transmission on a b channel + *---------------------------------------------------------------------------*/ +static void +isic_bchannel_start(int unit, int h_chan) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + + register isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + register int next_len; + register int len; + + int s; + int activity = -1; + int cmd = 0; + + s = SPLI4B(); /* enter critical section */ + if(chan->state & HSCX_TX_ACTIVE) /* already running ? */ + { + splx(s); + return; /* yes, leave */ + } + + /* get next mbuf from queue */ + + IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); + + if(chan->out_mbuf_head == NULL) /* queue empty ? */ + { + splx(s); /* leave critical section */ + return; /* yes, exit */ + } + + /* init current mbuf values */ + + chan->out_mbuf_cur = chan->out_mbuf_head; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + + /* activity indicator for timeout handling */ + + if(chan->bprot == BPROT_NONE) + { + if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) + activity = ACT_TX; + } + else + { + activity = ACT_TX; + } + + chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */ + + if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */ + { + i4b_trace_hdr_t hdr; + hdr.unit = unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + + len = 0; /* # of chars put into HSCX tx fifo this time */ + + /* + * fill the HSCX tx fifo with data from the current mbuf. if + * current mbuf holds less data than HSCX fifo length, try to + * get the next mbuf from (a possible) mbuf chain. if there is + * not enough data in a single mbuf or in a chain, then this + * is the last mbuf and we tell the HSCX that it has to send + * CRC and closing flag + */ + + while((len < sc->sc_bfifolen) && chan->out_mbuf_cur) + { + /* + * put as much data into the HSCX fifo as is + * available from the current mbuf + */ + + if((len + chan->out_mbuf_cur_len) >= sc->sc_bfifolen) + next_len = sc->sc_bfifolen - len; + else + next_len = chan->out_mbuf_cur_len; + +#ifdef NOTDEF + printf("b:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ", + chan->out_mbuf_head, + chan->out_mbuf_cur, + chan->out_mbuf_cur_ptr, + chan->out_mbuf_cur_len, + len, + next_len); +#endif + + /* wait for tx fifo write enabled */ + + isic_hscx_waitxfw(sc, h_chan); + + /* write what we have from current mbuf to HSCX fifo */ + + HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, next_len); + + len += next_len; /* update # of bytes written */ + chan->txcount += next_len; /* statistics */ + chan->out_mbuf_cur_ptr += next_len; /* data ptr */ + chan->out_mbuf_cur_len -= next_len; /* data len */ + + /* + * in case the current mbuf (of a possible chain) data + * has been put into the fifo, check if there is a next + * mbuf in the chain. If there is one, get ptr to it + * and update the data ptr and the length + */ + + if((chan->out_mbuf_cur_len <= 0) && + ((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL)) + { + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + } + } + + /* + * if there is either still data in the current mbuf and/or + * there is a successor on the chain available issue just + * a XTF (transmit) command to HSCX. if ther is no more + * data available from the current mbuf (-chain), issue + * an XTF and an XME (message end) command which will then + * send the CRC and the closing HDLC flag sequence + */ + + if(chan->out_mbuf_cur && (chan->out_mbuf_cur_len > 0)) + { + /* + * more data available, send current fifo out. + * next xfer to HSCX tx fifo is done in the + * HSCX interrupt routine. + */ + + cmd |= HSCX_CMDR_XTF; + } + else + { + /* end of mbuf chain */ + + if(chan->bprot == BPROT_NONE) + cmd |= HSCX_CMDR_XTF; + else + cmd |= HSCX_CMDR_XTF | HSCX_CMDR_XME; + + i4b_Bfreembuf(chan->out_mbuf_head); /* free mbuf chain */ + + chan->out_mbuf_head = NULL; + chan->out_mbuf_cur = NULL; + chan->out_mbuf_cur_ptr = NULL; + chan->out_mbuf_cur_len = 0; + } + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity); + + if(cmd) + isic_hscx_cmd(sc, h_chan, cmd); + + splx(s); +} + +/*---------------------------------------------------------------------------* + * fill statistics struct + *---------------------------------------------------------------------------*/ +static void +isic_bchannel_stat(int unit, int h_chan, bchan_statistics_t *bsp) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + int s; + + s = SPLI4B(); + + bsp->outbytes = chan->txcount; + bsp->inbytes = chan->rxcount; + + chan->txcount = 0; + chan->rxcount = 0; + + splx(s); +} + +/*---------------------------------------------------------------------------* + * return the address of isic drivers linktab + *---------------------------------------------------------------------------*/ +static isdn_link_t * +isic_ret_linktab(int unit, int channel) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + isic_Bchan_t *chan = &sc->sc_chan[channel]; + + return(&chan->isdn_linktab); +} + +/*---------------------------------------------------------------------------* + * set the driver linktab in the b channel softc + *---------------------------------------------------------------------------*/ +static void +isic_set_linktab(int unit, int channel, drvr_link_t *dlt) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + isic_Bchan_t *chan = &sc->sc_chan[channel]; + + chan->drvr_linktab = dlt; +} + +/*---------------------------------------------------------------------------* + * initialize our local linktab + *---------------------------------------------------------------------------*/ +void +isic_init_linktab(struct isic_softc *sc) +{ + isic_Bchan_t *chan = &sc->sc_chan[HSCX_CH_A]; + isdn_link_t *lt = &chan->isdn_linktab; + + /* make sure the hardware driver is known to layer 4 */ + ctrl_types[CTRL_PASSIVE].set_linktab = isic_set_linktab; + ctrl_types[CTRL_PASSIVE].get_linktab = isic_ret_linktab; + + /* local setup */ + lt->unit = sc->sc_unit; + lt->channel = HSCX_CH_A; + lt->bch_config = isic_bchannel_setup; + lt->bch_tx_start = isic_bchannel_start; + lt->bch_stat = isic_bchannel_stat; + lt->tx_queue = &chan->tx_queue; + + /* used by non-HDLC data transfers, i.e. telephony drivers */ + lt->rx_queue = &chan->rx_queue; + + /* used by HDLC data transfers, i.e. ipr and isp drivers */ + lt->rx_mbuf = &chan->in_mbuf; + + chan = &sc->sc_chan[HSCX_CH_B]; + lt = &chan->isdn_linktab; + + lt->unit = sc->sc_unit; + lt->channel = HSCX_CH_B; + lt->bch_config = isic_bchannel_setup; + lt->bch_tx_start = isic_bchannel_start; + lt->bch_stat = isic_bchannel_stat; + lt->tx_queue = &chan->tx_queue; + + /* used by non-HDLC data transfers, i.e. telephony drivers */ + lt->rx_queue = &chan->rx_queue; + + /* used by HDLC data transfers, i.e. ipr and isp drivers */ + lt->rx_mbuf = &chan->in_mbuf; +} + +/*---------------------------------------------------------------------------* + * telephony silence detection + *---------------------------------------------------------------------------*/ + +#define TEL_IDLE_MIN (BCH_MAX_DATALEN/2) + +int +isic_hscx_silence(unsigned char *data, int len) +{ + register int i = 0; + register int j = 0; + + /* count idle bytes */ + + for(;i < len; i++) + { + if((*data >= 0xaa) && (*data <= 0xac)) + j++; + data++; + } + +#ifdef NOTDEF + printf("isic_hscx_silence: got %d silence bytes in frame\n", j); +#endif + + if(j < (TEL_IDLE_MIN)) + return(0); + else + return(1); + +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_ctx_s0P.c b/sys/i4b/layer1/i4b_ctx_s0P.c new file mode 100644 index 0000000..f9e6b7f --- /dev/null +++ b/sys/i4b/layer1/i4b_ctx_s0P.c @@ -0,0 +1,366 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Creatix PnP cards + * ============================================================ + * + * $Id: i4b_ctx_s0P.c,v 1.17 1998/12/16 09:32:50 hm Exp $ + * + * last edit-date: [Mon Dec 14 17:26:30 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +#include "isic.h" +#include "opt_i4b.h" +#include "pnp.h" + +#else + +#define NISIC 1 +#define NPNP 1 + +#endif + +#if (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P) + +#include <sys/param.h> + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#ifndef __FreeBSD__ +static u_int8_t ctxs0P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void ctxs0P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void ctxs0P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void ctxs0P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +void isic_attach_Cs0P(struct isic_softc *sc); +#endif + +#ifdef __FreeBSD__ +#include <i386/isa/pnp.h> +extern void isicintr ( int unit ); +#endif + +/*---------------------------------------------------------------------------* + * Creatix ISDN-S0 P&P ISAC get fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +ctxs0P_read_fifo(void *buf, const void *base, size_t len) +{ + insb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +ctxs0P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_read_multi_1(t, h, o + 0x3e, buf, size); +} + +#endif + +/*---------------------------------------------------------------------------* + * Creatix ISDN-S0 P&P ISAC put fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +ctxs0P_write_fifo(void *base, const void *buf, size_t len) +{ + outsb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +ctxs0P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * Creatix ISDN-S0 P&P ISAC put register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +ctxs0P_write_reg(u_char *base, u_int offset, u_int v) +{ + outb((int)base + offset, (u_char)v); +} + +#else + +static void +ctxs0P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_1(t, h, o + offs, data); +} +#endif + +/*---------------------------------------------------------------------------* + * Creatix ISDN-S0 P&P ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +ctxs0P_read_reg(u_char *base, u_int offset) +{ + return (inb((int)base + offset)); +} + +#else + +static u_int8_t +ctxs0P_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + return bus_space_read_1(t, h, o + offs); +} + +#endif + +#ifdef __FreeBSD__ + +/*---------------------------------------------------------------------------* + * isic_probe_Cs0P - probe for Creatix ISDN-S0 P&P and compatibles + *---------------------------------------------------------------------------*/ +int +isic_probe_Cs0P(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Creatix ISDN-S0 P&P!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq) - 1) + { + case 3: + case 5: + case 7: + case 10: + case 11: + case 12: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Creatix ISDN-S0 P&P!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Creatix ISDN-S0 P&P!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + dev->id_msize = 0; + + if(iobase2 == 0) + { + printf("isic%d: Error, iobase2 is 0 for Creatix ISDN-S0 P&P!\n", + dev->id_unit); + return(0); + } + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0x120: + case 0x180: +/*XXX*/ break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Creatix ISDN-S0 P&P!\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = ctxs0P_read_reg; + sc->writereg = ctxs0P_write_reg; + + sc->readfifo = ctxs0P_read_fifo; + sc->writefifo = ctxs0P_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_CS0P; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t) dev->id_iobase - 0x20; + HSCX_A_BASE = (caddr_t) iobase2 - 0x20; + HSCX_B_BASE = (caddr_t) iobase2; + + /* + * Read HSCX A/B VSTR. Expected value for the Creatix PnP card is + * 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Creatix PnP\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_s0163P - attach Creatix ISDN-S0 P&P + *---------------------------------------------------------------------------*/ +int +isic_attach_Cs0P(struct isa_device *dev, unsigned int iobase2) +{ + outb((dev->id_iobase) + 0x1c, 0); + DELAY(SEC_DELAY / 10); + outb((dev->id_iobase) + 0x1c, 1); + DELAY(SEC_DELAY / 10); + return(1); +} + +#else /* !__FreeBSD__ */ + +void +isic_attach_Cs0P(struct isic_softc *sc) +{ + /* init card */ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, 0x1c, 0); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 0x1c, 1); + DELAY(SEC_DELAY / 10); + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = ctxs0P_read_reg; + sc->writereg = ctxs0P_write_reg; + + sc->readfifo = ctxs0P_read_fifo; + sc->writefifo = ctxs0P_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_CS0P; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; +} +#endif + +#endif /* (NISIC > 0) && (NPNP > 0) && defined(CRTX_S0_P) */ + diff --git a/sys/i4b/layer1/i4b_drn_ngo.c b/sys/i4b/layer1/i4b_drn_ngo.c new file mode 100644 index 0000000..a5f3d69 --- /dev/null +++ b/sys/i4b/layer1/i4b_drn_ngo.c @@ -0,0 +1,542 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_drn_ngo.c - Dr. Neuhaus Niccy GO@ and SAGEM Cybermod + * -------------------------------------------------------- + * + * $Id: i4b_drn_ngo.c,v 1.19 1998/12/16 09:32:50 hm Exp $ + * + * last edit-date: [Mon Dec 14 17:26:03 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +#include "isic.h" +#include "opt_i4b.h" +#include "pnp.h" + +#else + +#define NISIC 1 +#define NPNP 1 + +#endif + +#if (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +/*---------------------------------------------------------------------------* + * Niccy GO@ definitions + * + * the card uses 2 i/o addressranges each using 2 bytes + * + * addressrange 0: + * offset 0 - ISAC dataregister + * offset 1 - HSCX dataregister + * addressrange 1: + * offset 0 - ISAC addressregister + * offset 1 - HSCX addressregister + * + * to access an ISAC/HSCX register, you have to write the register + * number into the ISAC or HSCX addressregister and then read/write + * data for the ISAC/HSCX register into/from the corresponding + * dataregister. + * + * Thanks to Klaus Muehle of Dr. Neuhaus Telekommunikation for giving + * out this information! + * + *---------------------------------------------------------------------------*/ +#define NICCY_PORT_MIN 0x200 +#define NICCY_PORT_MAX 0x3e0 + +#define HSCX_ABIT 0x1000 /* flag, HSCX A is meant */ +#define HSCX_BBIT 0x2000 /* flag, HSCX B is meant */ + +#define HSCX_BOFF 0x40 + +#define ADDR_OFF 2 /* address register range offset XXX */ + +#define ISAC_DATA 0 +#define HSCX_DATA 1 + +#define ISAC_ADDR 0 +#define HSCX_ADDR 1 + +#ifdef __FreeBSD__ + +#if 0 +#define HSCXADEBUG +#define HSCXBDEBUG +#define ISACDEBUG +#else +#undef HSCXADEBUG +#undef HSCXBDEBUG +#undef ISACDEBUG +#endif + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ read fifo routine + *---------------------------------------------------------------------------*/ +static void +drnngo_read_fifo(void *buf, const void *base, size_t len) +{ + register int offset; + register u_int data; + + int x = SPLI4B(); + + if((u_int)base & HSCX_ABIT) + { + (u_int)base &= ~HSCX_ABIT; + (u_int)data = ((u_int)base + HSCX_DATA); + (u_int)base += (ADDR_OFF + HSCX_ADDR); + offset = 0; +#ifdef HSCXADEBUG +printf("GO/A/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + else if((u_int)base & HSCX_BBIT) + { + (u_int)base &= ~HSCX_BBIT; + (u_int)data = ((u_int)base + HSCX_DATA); + (u_int)base += (ADDR_OFF + HSCX_ADDR); + offset = HSCX_BOFF; +#ifdef HSCXBDEBUG +printf("GO/B/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + else + { + (u_int)data = ((u_int)base + ISAC_DATA); + (u_int)base += (ADDR_OFF + ISAC_ADDR); + offset = 0; +#ifdef ISACDEBUG +printf("GO/I/frd: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + + for(;len > 0; len--, offset++) + { + outb((int)base, (u_char)offset); + *((u_char *)buf + offset) = inb((int)data); + } + + splx(x); +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ write fifo routine + *---------------------------------------------------------------------------*/ +static void +drnngo_write_fifo(void *base, const void *buf, size_t len) +{ + register int offset; + register u_int data; + + int x = SPLI4B(); + + if((u_int)base & HSCX_ABIT) + { + (u_int)base &= ~HSCX_ABIT; + (u_int)data = ((u_int)base + HSCX_DATA); + (u_int)base += (ADDR_OFF + HSCX_ADDR); + offset = 0; +#ifdef HSCXADEBUG +printf("GO/A/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + else if((u_int)base & HSCX_BBIT) + { + (u_int)base &= ~HSCX_BBIT; + (u_int)data = ((u_int)base + HSCX_DATA); + (u_int)base += (ADDR_OFF + HSCX_ADDR); + offset = HSCX_BOFF; +#ifdef HSCXBDEBUG +printf("GO/B/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + else + { + (u_int)data = ((u_int)base + ISAC_DATA); + (u_int)base += (ADDR_OFF + ISAC_ADDR); + offset = 0; +#ifdef ISACDEBUG +printf("GO/I/fwr: base=0x%x, data=0x%x, len=%d\n", base, data, len); +#endif + } + + for(;len > 0; len--, offset++) + { + outb((int)base, (u_char)offset); + outb((int)data, *((u_char *)buf + offset)); + } + + splx(x); +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ write register routine + *---------------------------------------------------------------------------*/ +static void +drnngo_write_reg(u_char *base, u_int offset, u_int v) +{ + int x = SPLI4B(); + if((u_int)base & HSCX_ABIT) + { + (u_int)base &= ~HSCX_ABIT; + outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset); + outb((int)base + HSCX_DATA, (u_char)v); +#ifdef HSCXADEBUG +printf("GO/A/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA, + (u_char)offset, (u_char)v); +#endif + } + else if((u_int)base & HSCX_BBIT) + { + (u_int)base &= ~HSCX_BBIT; + outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF)); + outb((int)base + HSCX_DATA, (u_char)v); +#ifdef HSCXBDEBUG +printf("GO/B/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA, + (u_char)(offset + HSCX_BOFF), (u_char)v); +#endif + } + else + { + outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset); + outb((int)base + ISAC_DATA, (u_char)v); +#ifdef ISACDEBUG +printf("GO/I/rwr: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA, + (u_char)offset, (u_char)v); +#endif + } + splx(x); +} + +/*---------------------------------------------------------------------------* + * Dr. Neuhaus Niccy GO@ read register routine + *---------------------------------------------------------------------------*/ +static u_char +drnngo_read_reg(u_char *base, u_int offset) +{ + u_char val; + int x = SPLI4B(); + + if((u_int)base & HSCX_ABIT) + { + (u_int)base &= ~HSCX_ABIT; + outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)offset); + val = inb((int)base + HSCX_DATA); +#ifdef HSCXADEBUG +printf("GO/A/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA, + (u_char)offset, (u_char)val); +#endif + } + else if((u_int)base & HSCX_BBIT) + { + (u_int)base &= ~HSCX_BBIT; + outb((int)base + ADDR_OFF + HSCX_ADDR, (u_char)(offset + HSCX_BOFF)); + val = inb((int)base + HSCX_DATA); +#ifdef HSCXBDEBUG +printf("GO/B/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + HSCX_ADDR, (int)base + HSCX_DATA, + (u_char)(offset + HSCX_BOFF), (u_char)val); +#endif + } + else + { + outb((int)base + ADDR_OFF + ISAC_ADDR, (u_char)offset); + val = inb((int)base + ISAC_DATA); +#ifdef ISACDEBUG +printf("GO/I/rrd: base=0x%x, addr=0x%x, offset=0x%x, val=0x%x\n", + (int)base + ADDR_OFF + ISAC_ADDR, (int)base + ISAC_DATA, + (u_char)offset, (u_char)val); +#endif + } + splx(x); + return(val); +} + +/*---------------------------------------------------------------------------* + * isic_probe_drnngo - probe for Dr. Neuhaus Niccy GO@ + *---------------------------------------------------------------------------*/ +int +isic_probe_drnngo(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq)-1) + { + case 3: + case 4: + case 5: + case 9: + case 10: + case 11: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + dev->id_msize = 0; + + /* check if we got an iobase */ + + if(dev->id_iobase < NICCY_PORT_MIN || dev->id_iobase > NICCY_PORT_MAX) + { + printf("isic%d: Error, invalid iobase 0x%x specified for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit, dev->id_iobase); + return(0); + } + sc->sc_port = dev->id_iobase; + + if(iobase2 == 0) + { + printf("isic%d: Error, iobase2 is 0 for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit); + return(0); + } + + if(iobase2 < NICCY_PORT_MIN || iobase2 > NICCY_PORT_MAX) + { + printf("isic%d: Error, invalid port1 0x%x specified for Dr. Neuhaus Niccy GO@!\n", + dev->id_unit, iobase2); + return(0); + } + +/*XXX*/ if((dev->id_iobase + 2) != iobase2) + { + printf("isic%d: Error, port1 must be (port0+2) for Dr.Neuhaus Niccy GO@!\n", + dev->id_unit); + return(0); + } + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = drnngo_read_reg; + sc->writereg = drnngo_write_reg; + + sc->readfifo = drnngo_read_fifo; + sc->writefifo = drnngo_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_DRNNGO; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t)dev->id_iobase; + HSCX_A_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_ABIT); + HSCX_B_BASE = (caddr_t)(((u_int)dev->id_iobase) | HSCX_BBIT); + + /* + * Read HSCX A/B VSTR. Expected value for Dr. Neuhaus Niccy GO@ based + * boards is 0x05 in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Dr. Neuhaus Niccy GO@\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_drnngo - attach Dr. Neuhaus Niccy GO@ + *---------------------------------------------------------------------------*/ +int +isic_attach_drnngo(struct isa_device *dev, unsigned int iobase2) +{ + return (1); +} + +#else + +static u_int8_t drnngo_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void drnngo_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void drnngo_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void drnngo_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +void isic_attach_drnngo __P((struct isic_softc *sc)); + +/* + * Mapping from "what" parameter to offsets into the io map + */ +static struct { + bus_size_t oa, /* address register offset */ + od, /* data register offset */ + or; /* additional chip register offset */ +} offset[] = +{ + { ISAC_ADDR, ISAC_DATA, 0 }, /* ISAC access */ + { HSCX_ADDR, HSCX_DATA, 0 }, /* HSCX A access */ + { HSCX_ADDR, HSCX_DATA, HSCX_BOFF } /* HSCX B access */ +}; + +static void +drnngo_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h; + bus_space_write_1(t, ha, offset[what].oa, offset[what].or); + bus_space_read_multi_1(t, hd, offset[what].od, buf, size); +} + +static void +drnngo_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h; + bus_space_write_1(t, ha, offset[what].oa, offset[what].or); + bus_space_write_multi_1(t, hd, offset[what].od, (u_int8_t*)buf, size); +} + +static void +drnngo_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h; + bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or); + bus_space_write_1(t, hd, offset[what].od, data); +} + +static u_int8_t +drnngo_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t hd = sc->sc_maps[0].h, ha = sc->sc_maps[1].h; + bus_space_write_1(t, ha, offset[what].oa, offs+offset[what].or); + return bus_space_read_1(t, hd, offset[what].od); +} + +void +isic_attach_drnngo(struct isic_softc *sc) +{ + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = drnngo_read_reg; + sc->writereg = drnngo_write_reg; + + sc->readfifo = drnngo_read_fifo; + sc->writefifo = drnngo_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_DRNNGO; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; +} + +#endif + +#endif /* (NISIC > 0) && (NPNP > 0) && defined(DRN_NGO) */ diff --git a/sys/i4b/layer1/i4b_dynalink.c b/sys/i4b/layer1/i4b_dynalink.c new file mode 100644 index 0000000..846e79a --- /dev/null +++ b/sys/i4b/layer1/i4b_dynalink.c @@ -0,0 +1,438 @@ +/* + * Copyright (c) 1998 Martijn Plak. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdn4bsd layer1 driver for Dynalink IS64PH isdn TA + * ================================================== + * + * $Id: i4b_dynalink.c,v 1.8 1998/12/17 04:55:38 hm Exp $ + * + * last edit-date: [Thu Dec 17 05:50:39 1998] + * + * written by Martijn Plak <tigrfhur@xs4all.nl> + * + * -mp 11 jun 1998 first try, code borrowed from Creatix driver + * -mp 18 jun 1998 cleaned up code + * -hm FreeBSD PnP + * -mp 17 dec 1998 made it compile again + * + *---------------------------------------------------------------------------*/ + +/* NOTES: + + This driver was written for the Dynalink IS64PH ISDN TA, based on two + Siemens chips (HSCX 21525 and ISAC 2186). It is sold in the Netherlands. + + model numbers found on (my) card: + IS64PH, TAS100H-N, P/N:89590555, TA200S100045521 + + chips: + Siemens PSB 21525N, HSCX TE V2.1 + Siemens PSB 2186N, ISAC-S TE V1.1 + 95MS14, PNP + + plug-and-play info: + device id "ASU1688" + vendor id 0x88167506 + serial 0x00000044 + i/o port 4 byte alignment, 4 bytes requested, + 10 bit i/o decoding, 0x100-0x3f8 (?) + irq 3,4,5,9,10,11,12,15, high true, edge sensitive + + At the moment I'm writing this Dynalink is replacing this card with + one based on a single Siemens chip (IPAC). It will apparently be sold + under the same model name. + + This driver might also work for Asuscom cards. +*/ + +#ifdef __FreeBSD__ + +#include "isic.h" +#include "opt_i4b.h" +#include "pnp.h" + +#else + +#define NISIC 1 +#define NPNP 1 + +#endif + +#if (NISIC > 0) && (NPNP > 0) && defined(DYNALINK) + +/* HEADERS +*/ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#if __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/pnp.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#ifdef __FreeBSD__ +static void dynalink_read_fifo(void *buf, const void *base, size_t len); +static void dynalink_write_fifo(void *base, const void *buf, size_t len); +static void dynalink_write_reg(u_char *base, u_int offset, u_int v); +static u_char dynalink_read_reg(u_char *base, u_int offset); + +extern struct isa_driver isicdriver; + +#else +static void dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size); +static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size); +static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data); +static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs); +void isic_attach_Dyn(struct isic_softc *sc); +#endif + +/* io address mapping */ +#define ISAC 0 +#define HSCX 1 +#define ADDR 2 + +/* ADDR bits */ +#define ADDRMASK 0x7F +#define RESET 0x80 + +/* HSCX register offsets */ +#define HSCXA 0x00 +#define HSCXB 0x40 + +#ifdef __FreeBSD__ +/* base address juggling */ +#define HSCXB_HACK 0x400 +#define IOBASE(addr) (((int)addr)&0x3FC) +#define IOADDR(addr) (((int)addr)&0x3FF) +#define IS_HSCXB_HACK(addr) ((((int)addr)&HSCXB_HACK)?HSCXB:HSCXA) + +/* ISIC probe and attach +*/ + +int +isic_probe_Dyn(struct isa_device *dev, unsigned int iobase2) +{ + + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Dynalink IS64PH.\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq) - 1) + { + case 3: + case 4: + case 5: + case 9: + case 10: + case 11: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Dynalink IS64PH.\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Dynalink IS64PH.\n", + dev->id_unit, (u_long)dev->id_maddr); + return (0); + } + dev->id_msize = 0; + + /* check if we got an iobase */ + if ( (dev->id_iobase < 0x100) || + (dev->id_iobase > 0x3f8) || + (dev->id_iobase & 3) ) + { + printf("isic%d: Error, invalid iobase 0x%x specified for Dynalink!\n", dev->id_unit, dev->id_iobase); + return(0); + } + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = dynalink_read_reg; + sc->writereg = dynalink_write_reg; + sc->readfifo = dynalink_read_fifo; + sc->writefifo = dynalink_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_DYNALINK; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + ISAC_BASE = (caddr_t) sc->sc_port; + HSCX_A_BASE = (caddr_t) sc->sc_port + 1; + HSCX_B_BASE = (caddr_t) sc->sc_port + 1 + HSCXB_HACK; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Dynalink\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +int +isic_attach_Dyn(struct isa_device *dev, unsigned int iobase2) +{ + outb((dev->id_iobase)+ADDR, RESET); + DELAY(SEC_DELAY / 10); + outb((dev->id_iobase)+ADDR, 0); + DELAY(SEC_DELAY / 10); + return(1); +} + +#else + +void isic_attach_Dyn(struct isic_softc *sc) +{ + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = dynalink_read_reg; + sc->writereg = dynalink_write_reg; + sc->readfifo = dynalink_read_fifo; + sc->writefifo = dynalink_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_DYNALINK; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("%s: HSCX VSTR test failed for Dynalink PnP\n", + sc->sc_dev.dv_xname); + printf("%s: HSC0: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR)); + printf("%s: HSC1: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR)); + return; + } + + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, RESET); + DELAY(SEC_DELAY / 10); + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ADDR, 0); + DELAY(SEC_DELAY / 10); +} + +#endif /* ISIC>0 && NPNP>0 && defined(DYNALINK) */ + +/* LOW-LEVEL DEVICE ACCESS + + NOTE: The isdn4bsd code expects the two HSCX channels at different + base addresses. I'm faking this, and remap them to the same address + in the low-level routines. Search for HSCXB_HACK and IS_HSCXB_HACK. + + REM: this is only true for the FreeBSD version of I4B! +*/ + +#ifdef __FreeBSD__ +static void +dynalink_read_fifo(void *buf, const void *base, size_t len) +{ + outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base)); + insb(IOADDR(base), (u_char *)buf, (u_int)len); +} +#else +static void +dynalink_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, 0); + bus_space_read_multi_1(t, h, ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA); + bus_space_read_multi_1(t, h, HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB); + bus_space_read_multi_1(t, h, HSCX, buf, size); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static void +dynalink_write_fifo(void *base, const void *buf, size_t len) +{ + outb(IOBASE(base)+ADDR, 0+IS_HSCXB_HACK(base)); + outsb(IOADDR(base), (u_char *)buf, (u_int)len); +} +#else +static void dynalink_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, 0); + bus_space_write_multi_1(t, h, ISAC, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA); + bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB); + bus_space_write_multi_1(t, h, HSCX, (u_int8_t*)buf, size); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static void +dynalink_write_reg(u_char *base, u_int offset, u_int v) +{ + outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK); + outb(IOADDR(base), (u_char)v); +} +#else +static void dynalink_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, offs); + bus_space_write_1(t, h, ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA+offs); + bus_space_write_1(t, h, HSCX, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB+offs); + bus_space_write_1(t, h, HSCX, data); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static u_char +dynalink_read_reg(u_char *base, u_int offset) +{ + outb(IOBASE(base)+ADDR, (offset+IS_HSCXB_HACK(base))&ADDRMASK); + return (inb(IOADDR(base))); +} +#else +static u_int8_t dynalink_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR, offs); + return bus_space_read_1(t, h, ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR, HSCXA+offs); + return bus_space_read_1(t, h, HSCX); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR, HSCXB+offs); + return bus_space_read_1(t, h, HSCX); + } + return 0; +} +#endif + +#endif /* (NISIC > 0) && (NPNP > 0) && defined(DYNALINK) */ diff --git a/sys/i4b/layer1/i4b_elsa_isdnmc.c b/sys/i4b/layer1/i4b_elsa_isdnmc.c new file mode 100644 index 0000000..c6987f5 --- /dev/null +++ b/sys/i4b/layer1/i4b_elsa_isdnmc.c @@ -0,0 +1,305 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * ELSA MicroLink ISDN/MC card specific routines + * --------------------------------------------- + * + * $Id: i4b_elsa_isdnmc.c,v 1.2 1998/12/05 18:04:33 hm Exp $ + * + * last edit-date: [Tue Dec 1 07:45:53 1998] + * + * -mh added support for elsa ISDN/mc + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif + +#if NISIC > 0 && defined(ELSA_ISDNMC) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/layer1/pcmcia_isic.h> + +#ifndef __FreeBSD__ +/* PCMCIA support routines */ +static u_int8_t elsa_isdnmc_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void elsa_isdnmc_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void elsa_isdnmc_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void elsa_isdnmc_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/* + * The ELSA MicroLink ISDN/MC uses one contigous IO region, + * mapped by the pcmcia code. + * The chip access is via three ports: + */ +#define ISAC_DATA 1 /* ISAC dataport at offset 1 */ +#define HSCX_DATA 2 /* HSCX dataport at offset 2 */ +#define ADDR_LATCH 4 /* address latch at offset 4 */ + +/* This is very similar to the ELSA QuickStep 1000 (ISA) card */ + +/*---------------------------------------------------------------------------* + * read fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +elsa_isdnmc_read_fifo(void *buf, const void *base, size_t len) +{ +} +#else +static void +elsa_isdnmc_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR_LATCH, 0); + bus_space_read_multi_1(t, h, ISAC_DATA, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR_LATCH, 0); + bus_space_read_multi_1(t, h, HSCX_DATA, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR_LATCH, 0x40); + bus_space_read_multi_1(t, h, HSCX_DATA, buf, size); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * write fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +elsa_isdnmc_write_fifo(void *base, const void *buf, size_t len) +{ +} +#else +static void +elsa_isdnmc_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR_LATCH, 0); + bus_space_write_multi_1(t, h, ISAC_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR_LATCH, 0); + bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR_LATCH, 0x40); + bus_space_write_multi_1(t, h, HSCX_DATA, (u_int8_t*)buf, size); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * write register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +elsa_isdnmc_write_reg(u_char *base, u_int offset, u_int v) +{ +} +#else +static void +elsa_isdnmc_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR_LATCH, offs); + bus_space_write_1(t, h, ISAC_DATA, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR_LATCH, offs); + bus_space_write_1(t, h, HSCX_DATA, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs); + bus_space_write_1(t, h, HSCX_DATA, data); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * read register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static u_char +elsa_isdnmc_read_reg(u_char *base, u_int offset) +{ + return 0; +} +#else +static u_int8_t +elsa_isdnmc_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ADDR_LATCH, offs); + return bus_space_read_1(t, h, ISAC_DATA); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ADDR_LATCH, offs); + return bus_space_read_1(t, h, HSCX_DATA); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ADDR_LATCH, 0x40+offs); + return bus_space_read_1(t, h, HSCX_DATA); + } + return 0; +} +#endif + +#ifdef __FreeBSD__ +#else + +/* + * XXX - one time only! Some of this has to go into an enable + * function, with apropriate counterpart in disable, so a card + * could be removed an inserted again. But never mind for now, + * this won't work anyway for several reasons (both in NetBSD + * and in I4B). + */ +int +isic_attach_elsaisdnmc(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa) +{ + struct isic_softc *sc = &psc->sc_isic; + bus_space_tag_t t; + bus_space_handle_t h; + + /* Validate config info */ + if (cfe->num_memspace != 0) + printf(": unexpected number of memory spaces %d should be 0\n", + cfe->num_memspace); + if (cfe->num_iospace != 1) + printf(": unexpected number of memory spaces %d should be 1\n", + cfe->num_iospace); + + /* Allocate pcmcia space */ + if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length, + cfe->iospace[0].length, &psc->sc_pcioh)) + printf(": can't allocate i/o space\n"); + + /* map them */ + if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ? + PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, + cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) { + printf(": can't map i/o space\n"); + return 0; + } + + /* OK, this will work! */ + sc->sc_cardtyp = CARD_TYPEP_ELSAMLIMC; + + /* Setup bus space maps */ + sc->sc_num_mappings = 1; + MALLOC_MAPS(sc); + + /* Copy our handles/tags to the MI maps */ + sc->sc_maps[0].t = psc->sc_pcioh.iot; + sc->sc_maps[0].h = psc->sc_pcioh.ioh; + sc->sc_maps[0].offset = 0; + sc->sc_maps[0].size = 0; /* not our mapping */ + + t = sc->sc_maps[0].t; + h = sc->sc_maps[0].h; + + sc->clearirq = NULL; + sc->readreg = elsa_isdnmc_read_reg; + sc->writereg = elsa_isdnmc_write_reg; + + sc->readfifo = elsa_isdnmc_read_fifo; + sc->writefifo = elsa_isdnmc_write_fifo; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + return 1; +} +#endif + +#endif /* ISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_elsa_mcall.c b/sys/i4b/layer1/i4b_elsa_mcall.c new file mode 100644 index 0000000..36882e9 --- /dev/null +++ b/sys/i4b/layer1/i4b_elsa_mcall.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * ELSA MicroLink MC/all card specific routines + * -------------------------------------------- + * + * $Id: i4b_elsa_mcall.c,v 1.1 1998/12/02 06:44:27 hm Exp $ + * + * last edit-date: [Tue Dec 1 07:45:53 1998] + * + * -mh started support for ELSA MC/all + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif + +#if NISIC > 0 && defined(ELSA_MCALL) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> +#include <i4b/layer1/i4b_ipac.h> + +#include <i4b/layer1/pcmcia_isic.h> + +#ifndef __FreeBSD__ +/* PCMCIA support routines */ +static u_int8_t elsa_mcall_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void elsa_mcall_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void elsa_mcall_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void elsa_mcall_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * read fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static int PCMCIA_IO_BASE = 0; /* ap: XXX hack */ +static void +elsa_mcall_read_fifo(void *buf, const void *base, size_t len) +{ +} +#else +static void +elsa_mcall_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + /* + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + */ +} +#endif + +/*---------------------------------------------------------------------------* + * write fifo routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +elsa_mcall_write_fifo(void *base, const void *buf, size_t len) +{ +} +#else +static void +elsa_mcall_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + /* + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + */ +} +#endif + +/*---------------------------------------------------------------------------* + * write register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +elsa_mcall_write_reg(u_char *base, u_int offset, u_int v) +{ +} +#else +static void +elsa_mcall_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + /* + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + */ +} +#endif + +/*---------------------------------------------------------------------------* + * read register routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static u_char +elsa_mcall_read_reg(u_char *base, u_int offset) +{ + return 0; +} +#else +static u_int8_t +elsa_mcall_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + /* + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + */ + return 0; +} +#endif + +#ifdef __FreeBSD__ +#else + +/* + * XXX - one time only! Some of this has to go into an enable + * function, with apropriate counterpart in disable, so a card + * could be removed an inserted again. But never mind for now, + * this won't work anyway for several reasons (both in NetBSD + * and in I4B). + */ +int +isic_attach_elsamcall(struct pcmcia_isic_softc *psc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa) +{ + struct isic_softc *sc = &psc->sc_isic; + bus_space_tag_t t; + bus_space_handle_t h; + + /* Validate config info */ + if (cfe->num_memspace != 0) + printf(": unexpected number of memory spaces %d should be 0\n", + cfe->num_memspace); + if (cfe->num_iospace != 1) + printf(": unexpected number of memory spaces %d should be 1\n", + cfe->num_iospace); + + /* Allocate pcmcia space */ + if (pcmcia_io_alloc(pa->pf, 0, cfe->iospace[0].length, + cfe->iospace[0].length, &psc->sc_pcioh)) + printf(": can't allocate i/o space\n"); + + /* map them */ + if (pcmcia_io_map(pa->pf, ((cfe->flags & PCMCIA_CFE_IO16) ? + PCMCIA_WIDTH_IO16 : PCMCIA_WIDTH_IO8), 0, + cfe->iospace[0].length, &psc->sc_pcioh, &psc->sc_io_window)) { + printf(": can't map i/o space\n"); + return 0; + } + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_ELSAMLMCALL; + + /* Setup bus space maps */ + sc->sc_num_mappings = 1; + MALLOC_MAPS(sc); + + /* Copy our handles/tags to the MI maps */ + sc->sc_maps[0].t = psc->sc_pcioh.iot; + sc->sc_maps[0].h = psc->sc_pcioh.ioh; + sc->sc_maps[0].offset = 0; + sc->sc_maps[0].size = 0; /* not our mapping */ + + t = sc->sc_maps[0].t; + h = sc->sc_maps[0].h; + + sc->clearirq = NULL; + sc->readreg = elsa_mcall_read_reg; + sc->writereg = elsa_mcall_write_reg; + + sc->readfifo = elsa_mcall_read_fifo; + sc->writefifo = elsa_mcall_write_fifo; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + return 1; +} +#endif + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_elsa_qs1i.c b/sys/i4b/layer1/i4b_elsa_qs1i.c new file mode 100644 index 0000000..a3c8ddc --- /dev/null +++ b/sys/i4b/layer1/i4b_elsa_qs1i.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro ISA + * ===================================================================== + * + * $Id: i4b_elsa_qs1i.c,v 1.12 1998/12/16 09:32:50 hm Exp $ + * + * last edit-date: [Mon Dec 14 17:27:08 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +#include "isic.h" +#include "opt_i4b.h" +#include "pnp.h" + +#else + +#define NISIC 1 +#define NPNP 1 + +#endif + +#if (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#if __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/pnp.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#ifdef __FreeBSD__ +static void i4b_eq1i_clrirq(void* base); +#else +static void i4b_eq1i_clrirq(struct isic_softc *sc); +void isic_attach_Eqs1pi __P((struct isic_softc *sc)); +#endif + +/* masks for register encoded in base addr */ + +#define ELSA_BASE_MASK 0x0ffff +#define ELSA_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ELSA_IDISAC 0x00000 +#define ELSA_IDHSCXA 0x10000 +#define ELSA_IDHSCXB 0x20000 + +/* offsets from base address */ + +#define ELSA_OFF_ISAC 0x00 +#define ELSA_OFF_HSCX 0x02 +#define ELSA_OFF_OFF 0x03 +#define ELSA_OFF_CTRL 0x04 +#define ELSA_OFF_CFG 0x05 +#define ELSA_OFF_TIMR 0x06 +#define ELSA_OFF_IRQ 0x07 + +/* control register (write access) */ + +#define ELSA_CTRL_LED_YELLOW 0x02 +#define ELSA_CTRL_LED_GREEN 0x08 +#define ELSA_CTRL_RESET 0x20 +#define ELSA_CTRL_TIMEREN 0x80 +#define ELSA_CTRL_SECRET 0x50 + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA clear IRQ routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +static void +i4b_eq1i_clrirq(void* base) +{ + outb((u_int)base + ELSA_OFF_IRQ, 0); +} + +#else +static void +i4b_eq1i_clrirq(struct isic_softc *sc) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0); +} +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC get fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pi_read_fifo(void *buf, const void *base, size_t len) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len); + } +} + +#else + +static void +eqs1pi_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_read_multi_1(t, h, ELSA_OFF_HSCX, buf, size); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC put fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pi_write_fifo(void *base, const void *buf, size_t len) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0x40); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX), (u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, 0); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC), (u_char *)buf, (u_int)len); + } +} + +#else + +static void +eqs1pi_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_ISAC, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40); + bus_space_write_multi_1(t, h, ELSA_OFF_HSCX, (u_int8_t*)buf, size); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC put register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pi_write_reg(u_char *base, u_int offset, u_int v) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40)); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX, (u_char)v); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC, (u_char)v); + } +} + +#else + +static void +eqs1pi_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + bus_space_write_1(t, h, ELSA_OFF_HSCX, data); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/ISA ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +eqs1pi_read_reg(u_char *base, u_int offset) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)(offset+0x40)); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX)); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_HSCX)); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_OFF, (u_char)offset); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ISAC)); + } +} + +#else + +static u_int8_t +eqs1pi_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_OFF, offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_OFF, 0x40+offs); + return bus_space_read_1(t, h, ELSA_OFF_HSCX); + } + return 0; +} + +#endif + +#ifdef __FreeBSD__ + +/*---------------------------------------------------------------------------* + * isic_probe_Eqs1pi - probe for ELSA QuickStep 1000pro/ISA and compatibles + *---------------------------------------------------------------------------*/ +int +isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/ISA!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq) - 1) + { + case 3: + case 4: + case 5: + case 7: + case 10: + case 11: + case 12: + case 15: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for ELSA QuickStep 1000pro/ISA!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for ELSA QuickStep 1000pro/ISA!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + dev->id_msize = 0; + + /* check if we got an iobase */ + + if(!((dev->id_iobase >= 0x160) && (dev->id_iobase <= 0x360))) + { + printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/ISA!\n", + dev->id_unit, dev->id_iobase); + return(0); + } + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + +/* XXX no "sc_clearirq" in sight... /phk + sc->sc_clearirq = i4b_eq1i_clrirq; +*/ + sc->readreg = eqs1pi_read_reg; + sc->writereg = eqs1pi_write_reg; + + sc->readfifo = eqs1pi_read_fifo; + sc->writefifo = eqs1pi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDISAC); + HSCX_A_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXA); + HSCX_B_BASE = (caddr_t) ((u_int)dev->id_iobase | ELSA_IDHSCXB); + + /* + * Read HSCX A/B VSTR. Expected value for the ELSA QuickStep 1000pro + * ISA card is 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for ELSA QuickStep 1000pro/ISA\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_s0163P - attach ELSA QuickStep 1000pro/ISA + *---------------------------------------------------------------------------*/ +int +isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2) +{ + u_char byte = ELSA_CTRL_SECRET; + + byte &= ~ELSA_CTRL_RESET; + outb(dev->id_iobase + ELSA_OFF_CTRL, byte); + DELAY(20); + byte |= ELSA_CTRL_RESET; + outb(dev->id_iobase + ELSA_OFF_CTRL, byte); + + DELAY(20); + outb(dev->id_iobase + ELSA_OFF_IRQ, 0xff); + + return(1); +} + +#else /* !__FreeBSD__ */ + +void +isic_attach_Eqs1pi(struct isic_softc *sc) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + u_char byte = ELSA_CTRL_SECRET; + + byte &= ~ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + DELAY(20); + byte |= ELSA_CTRL_RESET; + bus_space_write_1(t, h, ELSA_OFF_CTRL, byte); + + DELAY(20); + bus_space_write_1(t, h, ELSA_OFF_IRQ, 0xff); + + /* setup access routines */ + + sc->clearirq = i4b_eq1i_clrirq; + sc->readreg = eqs1pi_read_reg; + sc->writereg = eqs1pi_write_reg; + + sc->readfifo = eqs1pi_read_fifo; + sc->writefifo = eqs1pi_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1ISA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; +} + +#endif + +#endif /* (NISIC > 0) && (NPNP > 0) && defined(ELSA_QS1ISA) */ diff --git a/sys/i4b/layer1/i4b_elsa_qs1p.c b/sys/i4b/layer1/i4b_elsa_qs1p.c new file mode 100644 index 0000000..b2b35d0 --- /dev/null +++ b/sys/i4b/layer1/i4b_elsa_qs1p.c @@ -0,0 +1,458 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for ELSA Quickstep 1000pro PCI + * ===================================================================== + * + * $Id: i4b_elsa_qs1p.c,v 1.4 1998/12/05 18:04:36 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:22:41 1998] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#include "pci.h" +#else +#define NISIC 1 +#endif + +#if (NISIC > 0) && /* (NPCI > 0) && */ defined(ELSA_QS1PCI) + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#if __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> +#include <i4b/layer1/i4b_ipac.h> + +#ifndef __FreeBSD__ +/* we don't have the function prototypes in the global i4b_l1.h any more */ +void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa)); +#endif + +/* masks for register encoded in base addr */ + +#define ELSA_BASE_MASK 0x0ffff +#define ELSA_OFF_MASK 0xf0000 + +/* register id's to be encoded in base addr */ + +#define ELSA_IDISAC 0x00000 +#define ELSA_IDHSCXA 0x10000 +#define ELSA_IDHSCXB 0x20000 +#define ELSA_IDIPAC 0x40000 + +/* offsets from base address */ + +#define ELSA_OFF_ALE 0x00 +#define ELSA_OFF_RW 0x01 + +#define ELSA_PORT0_MAPOFF PCI_MAPREG_START+4 +#define ELSA_PORT1_MAPOFF PCI_MAPREG_START+12 + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/PCI ISAC get fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pp_read_fifo(void *buf, const void *base, size_t len) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF); + insb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } +} + +#else + +static void +eqs1pp_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_read_multi_1(t, h, ELSA_OFF_RW, buf, size); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/PCI ISAC put fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pp_write_fifo(void *base, const void *buf, size_t len) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXB_OFF); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_HSCXA_OFF); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } + else /* if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, IPAC_ISAC_OFF); + outsb((((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW), (u_char *)buf, (u_int)len); + } +} + +#else + +static void +eqs1pp_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF); + bus_space_write_multi_1(t, h, ELSA_OFF_RW, (u_int8_t*)buf, size); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/PCI ISAC put register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +eqs1pp_write_reg(u_char *base, u_int offset, u_int v) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v); + } + else /* IPAC */ + { + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + outb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW, (u_char)v); + } +} + +#else + +static void +eqs1pp_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + case ISIC_WHAT_IPAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs); + bus_space_write_1(t, h, ELSA_OFF_RW, data); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * ELSA QuickStep 1000pro/PCI ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +eqs1pp_read_reg(u_char *base, u_int offset) +{ + if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXB) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXB_OFF)); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW)); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDHSCXA) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_HSCXA_OFF)); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW)); + } + else if(((u_int)base & ELSA_OFF_MASK) == ELSA_IDISAC) + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_ISAC_OFF)); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW)); + } + else /* IPAC */ + { + outb((u_int)((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_ALE, (u_char)(offset+IPAC_IPAC_OFF)); + return(inb(((u_int)base & ELSA_BASE_MASK) + ELSA_OFF_RW)); + } +} + +#else + +static u_int8_t +eqs1pp_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_ISAC_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXA_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_HSCXB_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + case ISIC_WHAT_IPAC: + { + bus_space_write_1(t, h, ELSA_OFF_ALE, IPAC_IPAC_OFF+offs); + return bus_space_read_1(t, h, ELSA_OFF_RW); + } + } + + return 0; +} + +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_Eqs1pp - attach for ELSA QuickStep 1000pro/PCI + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2) +{ + struct isic_softc *sc = &isic_sc[unit]; + + /* check max unit range */ + + if(unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for ELSA QuickStep 1000pro/PCI!\n", + unit, unit); + return(0); + } + sc->sc_unit = unit; + + /* setup iobase */ + + if((iobase2 <= 0) || (iobase2 > 0xffff)) + { + printf("isic%d: Error, invalid iobase 0x%x specified for ELSA QuickStep 1000pro/PCI!\n", + unit, iobase2); + return(0); + } + sc->sc_port = iobase2; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = eqs1pp_read_reg; + sc->writereg = eqs1pp_write_reg; + + sc->readfifo = eqs1pp_read_fifo; + sc->writefifo = eqs1pp_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDISAC); + HSCX_A_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXA); + HSCX_B_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDHSCXB); + IPAC_BASE = (caddr_t) ((u_int)iobase2 | ELSA_IDIPAC); + + /* enable hscx/isac irq's */ + IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */ + IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */ + (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2)); + IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */ + + outb(iobase1 + 0x4c, 0x41); /* enable card interrupt */ + + return (1); +} + +#else /* !FreeBSD */ + +void +isic_attach_Eqs1pp(sc, pa) + struct isic_softc *sc; + struct pci_attach_args *pa; +{ + /* setup io mappings */ + sc->sc_num_mappings = 2; + MALLOC_MAPS(sc); + sc->sc_maps[0].size = 0; + if (pci_mapreg_map(pa, ELSA_PORT0_MAPOFF, PCI_MAPREG_TYPE_IO, 0, + &sc->sc_maps[0].t, &sc->sc_maps[0].h, NULL, NULL)) { + printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); + return; + } + sc->sc_maps[1].size = 0; + if (pci_mapreg_map(pa, ELSA_PORT1_MAPOFF, PCI_MAPREG_TYPE_IO, 0, + &sc->sc_maps[1].t, &sc->sc_maps[1].h, NULL, NULL)) { + printf("%s: can't map i/o space\n", sc->sc_dev.dv_xname); + return; + } + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = eqs1pp_read_reg; + sc->writereg = eqs1pp_write_reg; + + sc->readfifo = eqs1pp_read_fifo; + sc->writefifo = eqs1pp_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_ELSAQS1PCI; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + /* setup chip type = IPAC ! */ + + sc->sc_ipac = 1; + sc->sc_bfifolen = IPAC_BFIFO_LEN; + + /* enable hscx/isac irq's */ + IPAC_WRITE(IPAC_MASK, (IPAC_MASK_INT1 | IPAC_MASK_INT0)); + + IPAC_WRITE(IPAC_ACFG, 0); /* outputs are open drain */ + IPAC_WRITE(IPAC_AOE, /* aux 5..2 are inputs, 7, 6 outputs */ + (IPAC_AOE_OE5 | IPAC_AOE_OE4 | IPAC_AOE_OE3 | IPAC_AOE_OE2)); + IPAC_WRITE(IPAC_ATX, 0xff); /* set all output lines high */ + + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 0x4c, 0x41); /* enable card interrupt */ +} + +#endif + +#endif /* (NISIC > 0) && defined(ELSA_QS1PCI) */ diff --git a/sys/i4b/layer1/i4b_hscx.c b/sys/i4b/layer1/i4b_hscx.c new file mode 100644 index 0000000..ed80a51 --- /dev/null +++ b/sys/i4b/layer1/i4b_hscx.c @@ -0,0 +1,672 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b - Siemens HSCX chip (B-channel) handling + * -------------------------------------------- + * + * $Id: i4b_hscx.c,v 1.37 1998/12/05 18:04:38 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:23:36 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#else +#define NISIC 1 /* doesn't matter in non-FreeBSD, config(8) d.t.r.t. */ +#endif +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <machine/stdarg.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_mbuf.h> + +/*---------------------------------------------------------------------------* + * HSCX IRQ Handler + *---------------------------------------------------------------------------*/ +void +isic_hscx_irq(register struct isic_softc *sc, u_char ista, int h_chan, u_char ex_irq) +{ + register isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + u_char exir = 0; + int activity = -1; + u_char cmd = 0; + + DBGL1(L1_H_IRQ, "isic_hscx_irq", ("%#x\n", ista)); + + if(ex_irq) + { + /* get channel extended irq reg */ + + exir = HSCX_READ(h_chan, H_EXIR); + + if(exir & HSCX_EXIR_RFO) + { + chan->stat_RFO++; + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: receive data overflow\n")); + } + + if((exir & HSCX_EXIR_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */ + { + chan->stat_XDU++; + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("ex_irq: xmit data underrun\n")); + isic_hscx_cmd(sc, h_chan, HSCX_CMDR_XRES); + + if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */ + { + i4b_Bfreembuf(chan->out_mbuf_head); + chan->out_mbuf_cur = chan->out_mbuf_head = NULL; + } + } + + } + + /* rx message end, end of frame */ + + if(ista & HSCX_ISTA_RME) + { + register int fifo_data_len; + u_char rsta; + int error = 0; + + rsta = HSCX_READ(h_chan, H_RSTA); + + if((rsta & 0xf0) != 0xa0) + { + if((rsta & HSCX_RSTA_VFR) == 0) + { + chan->stat_VFR++; + cmd |= (HSCX_CMDR_RHR); + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("received invalid Frame\n")); + error++; + } + + if(rsta & HSCX_RSTA_RDO) + { + chan->stat_RDO++; + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("receive data overflow\n")); + error++; + } + + if((rsta & HSCX_RSTA_CRC) == 0) + { + chan->stat_CRC++; + cmd |= (HSCX_CMDR_RHR); + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("CRC check failed\n")); + error++; + } + + if(rsta & HSCX_RSTA_RAB) + { + chan->stat_RAB++; + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("Receive message aborted\n")); + error++; + } + } + + fifo_data_len = ((HSCX_READ(h_chan, H_RBCL)) & + ((sc->sc_bfifolen)-1)); + + if(fifo_data_len == 0) + fifo_data_len = sc->sc_bfifolen; + + /* all error conditions checked, now decide and take action */ + + if(error == 0) + { + if(chan->in_mbuf == NULL) + { + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RME, cannot allocate mbuf!\n"); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + } + + fifo_data_len -= 1; /* last byte in fifo is RSTA ! */ + + if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN) + { + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, fifo_data_len); + + cmd |= (HSCX_CMDR_RMC); + isic_hscx_cmd(sc, h_chan, cmd); + cmd = 0; + + chan->in_len += fifo_data_len; + chan->rxcount += fifo_data_len; + + /* setup mbuf data length */ + + chan->in_mbuf->m_len = chan->in_len; + chan->in_mbuf->m_pkthdr.len = chan->in_len; + + if(sc->sc_trace & TRACE_B_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = sc->sc_unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); + } + + (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit); + + activity = ACT_RX; + + /* mark buffer ptr as unused */ + + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + else + { + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RME, in_len=%d, fifolen=%d\n", chan->in_len, fifo_data_len)); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + cmd |= (HSCX_CMDR_RHR | HSCX_CMDR_RMC); + } + } + else + { + if (chan->in_mbuf != NULL) + { + i4b_Bfreembuf(chan->in_mbuf); + chan->in_mbuf = NULL; + chan->in_cbptr = NULL; + chan->in_len = 0; + } + cmd |= (HSCX_CMDR_RMC); + } + } + + /* rx fifo full */ + + if(ista & HSCX_ISTA_RPF) + { + if(chan->in_mbuf == NULL) + { + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RPF, cannot allocate mbuf!\n"); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + } + + chan->rxcount += sc->sc_bfifolen; + + if((chan->in_len + sc->sc_bfifolen) <= BCH_MAX_DATALEN) + { + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen); + + chan->in_cbptr += sc->sc_bfifolen; + chan->in_len += sc->sc_bfifolen; + } + else + { + if(chan->bprot == BPROT_NONE) + { + /* setup mbuf data length */ + + chan->in_mbuf->m_len = chan->in_len; + chan->in_mbuf->m_pkthdr.len = chan->in_len; + + if(sc->sc_trace & TRACE_B_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = sc->sc_unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); + } + + /* move rx'd data to rx queue */ + + IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf); + + (*chan->drvr_linktab->bch_rx_data_ready)(chan->drvr_linktab->unit); + + if(!(isic_hscx_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len))) + activity = ACT_RX; + + /* alloc new buffer */ + + if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) + panic("L1 isic_hscx_irq: RPF, cannot allocate new mbuf!\n"); + + /* setup new data ptr */ + + chan->in_cbptr = chan->in_mbuf->m_data; + + /* read data from HSCX fifo */ + + HSCX_RDFIFO(h_chan, chan->in_cbptr, sc->sc_bfifolen); + + chan->in_cbptr += sc->sc_bfifolen; + chan->in_len = sc->sc_bfifolen; + + chan->rxcount += sc->sc_bfifolen; + } + else + { + DBGL1(L1_H_XFRERR, "isic_hscx_irq", ("RAWHDLC rx buffer overflow in RPF, in_len=%d\n", chan->in_len)); + chan->in_cbptr = chan->in_mbuf->m_data; + chan->in_len = 0; + cmd |= (HSCX_CMDR_RHR); + } + } + + /* command to release fifo space */ + + cmd |= HSCX_CMDR_RMC; + } + + /* transmit fifo empty, new data can be written to fifo */ + + if(ista & HSCX_ISTA_XPR) + { + /* + * for a description what is going on here, please have + * a look at isic_bchannel_start() in i4b_bchan.c ! + */ + + int activity = -1; + int len; + int nextlen; + + DBGL1(L1_H_IRQ, "isic_hscx_irq", ("unit %d, chan %d - XPR, Tx Fifo Empty!\n", sc->sc_unit, h_chan)); + + if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */ + { + IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); + + if(chan->out_mbuf_head == NULL) + { + chan->state &= ~HSCX_TX_ACTIVE; + (*chan->drvr_linktab->bch_tx_queue_empty)(chan->drvr_linktab->unit); + } + else + { + chan->state |= HSCX_TX_ACTIVE; + chan->out_mbuf_cur = chan->out_mbuf_head; + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = sc->sc_unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + + if(chan->bprot == BPROT_NONE) + { + if(!(isic_hscx_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) + activity = ACT_TX; + } + else + { + activity = ACT_TX; + } + } + } + + len = 0; + + while(chan->out_mbuf_cur && len != sc->sc_bfifolen) + { + nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len); + +#ifdef NOTDEF + printf("i:mh=%x, mc=%x, mcp=%x, mcl=%d l=%d nl=%d # ", + chan->out_mbuf_head, + chan->out_mbuf_cur, + chan->out_mbuf_cur_ptr, + chan->out_mbuf_cur_len, + len, + next_len); +#endif + + isic_hscx_waitxfw(sc, h_chan); /* necessary !!! */ + + HSCX_WRFIFO(h_chan, chan->out_mbuf_cur_ptr, nextlen); + cmd |= HSCX_CMDR_XTF; + + len += nextlen; + chan->txcount += nextlen; + + chan->out_mbuf_cur_ptr += nextlen; + chan->out_mbuf_cur_len -= nextlen; + + if(chan->out_mbuf_cur_len == 0) + { + if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL) + { + chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; + chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; + + if(sc->sc_trace & TRACE_B_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = sc->sc_unit; + hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_bcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); + } + } + else + { + if (chan->bprot != BPROT_NONE) + cmd |= HSCX_CMDR_XME; + i4b_Bfreembuf(chan->out_mbuf_head); + chan->out_mbuf_head = NULL; + } + + } + } + } + + if(cmd) /* is there a command for the HSCX ? */ + { + isic_hscx_cmd(sc, h_chan, cmd); /* yes, to HSCX */ + } + + /* call timeout handling routine */ + + if(activity == ACT_RX || activity == ACT_TX) + (*chan->drvr_linktab->bch_activity)(chan->drvr_linktab->unit, activity); +} + +/*---------------------------------------------------------------------------* + * HSCX initialization + * + * for telephony: extended transparent mode 1 + * for raw hdlc: transparent mode 0 + *---------------------------------------------------------------------------*/ +void +isic_hscx_init(struct isic_softc *sc, int h_chan, int activate) +{ + isic_Bchan_t *chan = &sc->sc_chan[h_chan]; + + HSCX_WRITE(h_chan, H_MASK, 0xff); /* mask irq's */ + + if(sc->sc_ipac) + { + /* CCR1: Power Up, Clock Mode 5 */ + HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */ + HSCX_CCR1_CM1); /* IPAC clock mode 5 */ + } + else + { + /* CCR1: Power Up, Clock Mode 5 */ + HSCX_WRITE(h_chan, H_CCR1, HSCX_CCR1_PU | /* power up */ + HSCX_CCR1_CM2 | /* HSCX clock mode 5 */ + HSCX_CCR1_CM0); + } + + /* XAD1: Transmit Address Byte 1 */ + HSCX_WRITE(h_chan, H_XAD1, 0xff); + + /* XAD2: Transmit Address Byte 2 */ + HSCX_WRITE(h_chan, H_XAD2, 0xff); + + /* RAH2: Receive Address Byte High Reg. 2 */ + HSCX_WRITE(h_chan, H_RAH2, 0xff); + + /* XBCH: reset Transmit Byte Count High */ + HSCX_WRITE(h_chan, H_XBCH, 0x00); + + /* RLCR: reset Receive Length Check Register */ + HSCX_WRITE(h_chan, H_RLCR, 0x00); + + /* CCR2: set tx/rx clock shift bit 0 */ + /* disable CTS irq, disable RIE irq*/ + HSCX_WRITE(h_chan, H_CCR2, HSCX_CCR2_XCS0|HSCX_CCR2_RCS0); + + /* XCCR: tx bit count per time slot */ + HSCX_WRITE(h_chan, H_XCCR, 0x07); + + /* RCCR: rx bit count per time slot */ + HSCX_WRITE(h_chan, H_RCCR, 0x07); + + if(sc->sc_bustyp == BUS_TYPE_IOM2) + { + switch(h_chan) + { + case HSCX_CH_A: /* Prepare HSCX channel A */ + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x2f); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x2f); + break; + + case HSCX_CH_B: /* Prepare HSCX channel B */ + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x03); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x03); + break; + } + } + else /* IOM 1 setup */ + { + /* TSAX: tx clock shift bits 1 & 2 */ + /* tx time slot number */ + HSCX_WRITE(h_chan, H_TSAX, 0x07); + + /* TSAR: rx clock shift bits 1 & 2 */ + /* rx time slot number */ + HSCX_WRITE(h_chan, H_TSAR, 0x07); + } + + if(activate) + { + if(chan->bprot == BPROT_RHDLC) + { + /* HDLC Frames, transparent mode 0 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_RAC|HSCX_MODE_RTS); + } + else + { + /* Raw Telephony, extended transparent mode 1 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS); + } + + isic_hscx_cmd(sc, h_chan, HSCX_CMDR_RHR|HSCX_CMDR_XRES); + } + else + { + /* TSAX: tx time slot */ + HSCX_WRITE(h_chan, H_TSAX, 0xff); + + /* TSAR: rx time slot */ + HSCX_WRITE(h_chan, H_TSAR, 0xff); + + /* Raw Telephony, extended transparent mode 1 */ + HSCX_WRITE(h_chan, H_MODE, + HSCX_MODE_MDS1|HSCX_MODE_MDS0|HSCX_MODE_ADM|HSCX_MODE_RTS); + } + + /* don't touch ICA, EXA and EXB bits, this could be HSCX_CH_B */ + /* always disable RSC and TIN */ + + chan->hscx_mask |= HSCX_MASK_RSC | HSCX_MASK_TIN; + + if(activate) + { + /* enable */ + chan->hscx_mask &= ~(HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR); + } + else + { + /* disable */ + chan->hscx_mask |= HSCX_MASK_RME | HSCX_MASK_RPF | HSCX_MASK_XPR; + } + + /* handle ICA, EXA, and EXB via interrupt mask of channel b */ + + if (h_chan == HSCX_CH_A) + { + if (activate) + HSCX_B_IMASK &= ~(HSCX_MASK_EXA | HSCX_MASK_ICA); + else + HSCX_B_IMASK |= HSCX_MASK_EXA | HSCX_MASK_ICA; + HSCX_WRITE(HSCX_CH_A, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } + else + { + if (activate) + HSCX_B_IMASK &= ~HSCX_MASK_EXB; + else + HSCX_B_IMASK |= HSCX_MASK_EXB; + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } + + /* clear spurious interrupts left over */ + + if(h_chan == HSCX_CH_A) + { + HSCX_READ(h_chan, H_EXIR); + HSCX_READ(h_chan, H_ISTA); + } + else /* mask ICA, because it must not be cleared by reading ISTA */ + { + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK | HSCX_MASK_ICA); + HSCX_READ(h_chan, H_EXIR); + HSCX_READ(h_chan, H_ISTA); + HSCX_WRITE(HSCX_CH_B, H_MASK, HSCX_B_IMASK); + } +} + +/*---------------------------------------------------------------------------* + * write command to HSCX command register + *---------------------------------------------------------------------------*/ +void +isic_hscx_cmd(struct isic_softc *sc, int h_chan, unsigned char cmd) +{ + int timeout = 20; + + while(((HSCX_READ(h_chan, H_STAR)) & HSCX_STAR_CEC) && timeout) + { + DELAY(10); + timeout--; + } + + if(timeout == 0) + { + DBGL1(L1_H_ERR, "isic_hscx_cmd", ("HSCX wait for CEC timeout!\n")); + } + + HSCX_WRITE(h_chan, H_CMDR, cmd); +} + +/*---------------------------------------------------------------------------* + * wait for HSCX transmit FIFO write enable + *---------------------------------------------------------------------------*/ +void +isic_hscx_waitxfw(struct isic_softc *sc, int h_chan) +{ +#define WAITVAL 50 +#define WAITTO 200 + + int timeout = WAITTO; + + while((!(((HSCX_READ(h_chan, H_STAR)) & + (HSCX_STAR_CEC | HSCX_STAR_XFW)) == HSCX_STAR_XFW)) && timeout) + { + DELAY(WAITVAL); + timeout--; + } + + if(timeout == 0) + { + DBGL1(L1_H_ERR, "isic_hscx_waitxfw", ("HSCX wait for XFW timeout!\n")); + } + else if (timeout != WAITTO) + { + DBGL1(L1_H_XFRERR, "isic_hscx_waitxfw", ("HSCX wait for XFW time: %d uS\n", (WAITTO-timeout)*50)); + } +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_hscx.h b/sys/i4b/layer1/i4b_hscx.h new file mode 100644 index 0000000..1b1640d --- /dev/null +++ b/sys/i4b/layer1/i4b_hscx.h @@ -0,0 +1,301 @@ +/* + * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * $Id: i4b_hscx.h,v 1.3 1998/02/13 17:00:31 hm Exp $ + * + * last edit-date: [Thu Feb 5 13:38:50 1998] + * + * -hm added AVM config register defs + * -hm split up for rewrite of Siemens chipset driver + * + *--------------------------------------------------------------------------- + */ + +#ifndef I4B_HSCX_H_ +#define I4B_HSCX_H_ + +enum HSCX_VERSIONS { + HSCX_VA1, /* 82525 A1 */ + HSCX_UNKN1, /* unknown 1 */ + HSCX_VA2, /* 82525 A2 */ + HSCX_UNKN3, /* unknown 3 */ + HSCX_VA3, /* 82525 A3 */ + HSCX_V21, /* 82525 2.1 */ + HSCX_UNKN /* unknown version */ +}; + +#define HSCX_CH_A 0 /* channel A */ +#define HSCX_CH_B 1 /* channel B */ + +#define HSCX_FIFO_LEN 32 /* 32 bytes FIFO on chip */ + +/* + * definitions of registers and bits for the HSCX ISDN chip. + */ + +typedef struct hscx_reg { + + /* 32 byte deep FIFO always first */ + + unsigned char hscx_fifo [HSCX_FIFO_LEN]; + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char hscx_ista; + unsigned char hscx_star; + unsigned char hscx_mode; + unsigned char hscx_timr; + unsigned char hscx_exir; + unsigned char hscx_rbcl; + unsigned char dummy_26; + unsigned char hscx_rsta; + unsigned char hscx_ral1; + unsigned char hscx_rhcr; + unsigned char dummy_2a; + unsigned char dummy_2b; + unsigned char hscx_ccr2; + unsigned char hscx_rbch; + unsigned char hscx_vstr; + unsigned char hscx_ccr; + unsigned char dummy_30; + unsigned char dummy_31; + unsigned char dummy_32; + unsigned char dummy_33; + } hscx_r; + struct { + unsigned char hscx_mask; + unsigned char hscx_cmdr; + unsigned char hscx_mode; + unsigned char hscx_timr; + unsigned char hscx_xad1; + unsigned char hscx_xad2; + unsigned char hscx_rah1; + unsigned char hscx_rah2; + unsigned char hscx_ral1; + unsigned char hscx_ral2; + unsigned char hscx_xbcl; + unsigned char hscx_bgr; + unsigned char hscx_ccr2; + unsigned char hscx_xbch; + unsigned char hscx_rlcr; + unsigned char hscx_ccr1; + unsigned char hscx_tsax; + unsigned char hscx_tsar; + unsigned char hscx_xccr; + unsigned char hscx_rccr; + } hscx_w; + } hscx_rw; +} hscx_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* HSCX read registers */ + +#define h_ista hscx_rw.hscx_r.hscx_ista +#define H_ISTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ista) +#define h_star hscx_rw.hscx_r.hscx_star +#define H_STAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_star) +#define h_mode hscx_rw.hscx_r.hscx_mode +#define H_MODE REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_mode) +#define h_timr hscx_rw.hscx_r.hscx_timr +#define H_TIMR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_timr) +#define h_exir hscx_rw.hscx_r.hscx_exir +#define H_EXIR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_exir) +#define h_rbcl hscx_rw.hscx_r.hscx_rbcl +#define H_RBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbcl) +#define h_rsta hscx_rw.hscx_r.hscx_rsta +#define H_RSTA REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rsta) +#define h_ral1 hscx_rw.hscx_r.hscx_ral1 +#define H_RAL1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ral1) +#define h_rhcr hscx_rw.hscx_r.hscx_rhcr +#define H_RHCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rhcr) +#define h_ccr2 hscx_rw.hscx_r.hscx_ccr2 +#define H_CCR2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr2) +#define h_rbch hscx_rw.hscx_r.hscx_rbch +#define H_RBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_rbch) +#define h_vstr hscx_rw.hscx_r.hscx_vstr +#define H_VSTR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_vstr) +#define h_ccr hscx_rw.hscx_r.hscx_ccr +#define H_CCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_r.hscx_ccr) + +/* HSCX write registers - for hscx_mode, hscx_timr, hscx_ral1, hscx_ccr2 */ +/* see read registers */ + +#define h_mask hscx_rw.hscx_w.hscx_mask +#define H_MASK REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_mask) +#define h_cmdr hscx_rw.hscx_w.hscx_cmdr +#define H_CMDR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_cmdr) +#define h_xad1 hscx_rw.hscx_w.hscx_xad1 +#define H_XAD1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad1) +#define h_xad2 hscx_rw.hscx_w.hscx_xad2 +#define H_XAD2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xad2) +#define h_rah1 hscx_rw.hscx_w.hscx_rah1 +#define H_RAH1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah1) +#define h_rah2 hscx_rw.hscx_w.hscx_rah2 +#define H_RAH2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rah2) +#define h_ral2 hscx_rw.hscx_w.hscx_ral2 +#define H_RAL2 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ral2) +#define h_xbcl hscx_rw.hscx_w.hscx_xbcl +#define H_XBCL REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbcl) +#define h_bgr hscx_rw.hscx_w.hscx_bgr +#define H_BGR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_bgr) +#define h_xbch hscx_rw.hscx_w.hscx_xbch +#define H_XBCH REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xbch) +#define h_rlcr hscx_rw.hscx_w.hscx_rlcr +#define H_RLCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rlcr) +#define h_ccr1 hscx_rw.hscx_w.hscx_ccr1 +#define H_CCR1 REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_ccr1) +#define h_tsax hscx_rw.hscx_w.hscx_tsax +#define H_TSAX REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsax) +#define h_tsar hscx_rw.hscx_w.hscx_tsar +#define H_TSAR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_tsar) +#define h_xccr hscx_rw.hscx_w.hscx_xccr +#define H_XCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_xccr) +#define h_rccr hscx_rw.hscx_w.hscx_rccr +#define H_RCCR REG_OFFSET(hscx_reg_t, hscx_rw.hscx_w.hscx_rccr) + +#define HSCX_ISTA_RME 0x80 +#define HSCX_ISTA_RPF 0x40 +#define HSCX_ISTA_RSC 0x20 +#define HSCX_ISTA_XPR 0x10 +#define HSCX_ISTA_TIN 0x08 +#define HSCX_ISTA_ICA 0x04 +#define HSCX_ISTA_EXA 0x02 +#define HSCX_ISTA_EXB 0x01 + +#define HSCX_MASK_RME 0x80 +#define HSCX_MASK_RPF 0x40 +#define HSCX_MASK_RSC 0x20 +#define HSCX_MASK_XPR 0x10 +#define HSCX_MASK_TIN 0x08 +#define HSCX_MASK_ICA 0x04 +#define HSCX_MASK_EXA 0x02 +#define HSCX_MASK_EXB 0x01 + +#define HSCX_EXIR_XMR 0x80 +#define HSCX_EXIR_XDU 0x40 +#define HSCX_EXIR_PCE 0x20 +#define HSCX_EXIR_RFO 0x10 +#define HSCX_EXIR_CSC 0x08 +#define HSCX_EXIR_RFS 0x04 + +/* the other bits are always 0 */ + +#define HSCX_STAR_XDOV 0x80 +#define HSCX_STAR_XFW 0x40 +#define HSCX_STAR_XRNR 0x20 +#define HSCX_STAR_RRNR 0x10 +#define HSCX_STAR_RLI 0x08 +#define HSCX_STAR_CEC 0x04 +#define HSCX_STAR_CTS 0x02 +#define HSCX_STAR_WFA 0x01 + +#define HSCX_CMDR_RMC 0x80 +#define HSCX_CMDR_RHR 0x40 +/* also known as XREP in transparent mode */ +#define HSCX_CMDR_RNR 0x20 +#define HSCX_CMDR_STI 0x10 +#define HSCX_CMDR_XTF 0x08 +#define HSCX_CMDR_XIF 0x04 +#define HSCX_CMDR_XME 0x02 +#define HSCX_CMDR_XRES 0x01 + +#define HSCX_MODE_MDS1 0x80 +#define HSCX_MODE_MDS0 0x40 +#define HSCX_MODE_ADM 0x20 +#define HSCX_MODE_TMD 0x10 +#define HSCX_MODE_RAC 0x08 +#define HSCX_MODE_RTS 0x04 +#define HSCX_MODE_TRS 0x02 +#define HSCX_MODE_TLP 0x01 + +#define HSCX_RSTA_VFR 0x80 +#define HSCX_RSTA_RDO 0x40 +#define HSCX_RSTA_CRC 0x20 +#define HSCX_RSTA_RAB 0x10 +#define HSCX_RSTA_HA1 0x08 +#define HSCX_RSTA_HA0 0x04 +#define HSCX_RSTA_CR 0x02 +#define HSCX_RSTA_LA 0x01 + +#define HSCX_RSTA_MASK 0xf0 /* the interesting ones */ + +/* only used in DMA mode */ +#define HSCX_XBCH_DMA 0x80 +#define HSCX_XBCH_NRM 0x40 +#define HSCX_XBCH_CAS 0x20 +#define HSCX_XBCH_XC 0x10 +/* the rest are bits 11 thru 8 of the byte count */ + +#define HSCX_RBCH_DMA 0x80 +#define HSCX_RBCH_NRM 0x40 +#define HSCX_RBCH_CAS 0x20 +#define HSCX_RBCH_OV 0x10 +/* the rest are bits 11 thru 8 of the byte count */ + +#define HSCX_VSTR_CD 0x80 +/* bits 6 thru 4 are 0 */ +/* bits 3 thru 0 are the version number */ + +#define HSCX_RLCR_RC 0x80 +/* the rest of the bits are used to set the received length */ + +#define HSCX_CCR1_PU 0x80 +/* bits 6 and 5 are SC1 SC0 */ +#define HSCX_CCR1_ODS 0x10 +#define HSCX_CCR1_ITF 0x08 +#define HSCX_CCR1_CM2 0x04 +#define HSCX_CCR1_CM1 0x02 +#define HSCX_CCR1_CM0 0x01 + +/* for clock mode 5 */ +#define HSCX_CCR2_SOC2 0x80 +#define HSCX_CCR2_SOC1 0x40 +#define HSCX_CCR2_XCS0 0x20 +#define HSCX_CCR2_RCS0 0x10 +#define HSCX_CCR2_TIO 0x08 +#define HSCX_CCR2_CIE 0x04 +#define HSCX_CCR2_RIE 0x02 +#define HSCX_CCR2_DIV 0x01 + +/* bits 7 thru 2 are TSNX */ +#define HSCX_TSAX_XCS2 0x02 +#define HSCX_TSAX_XCS1 0x01 + +/* bits 7 thru 2 are TSNR */ +#define HSCX_TSAR_RCS2 0x02 +#define HSCX_TSAR_RCS1 0x01 + +#endif /* I4B_HSCX_H_ */ diff --git a/sys/i4b/layer1/i4b_ipac.h b/sys/i4b/layer1/i4b_ipac.h new file mode 100644 index 0000000..79d8bc9 --- /dev/null +++ b/sys/i4b/layer1/i4b_ipac.h @@ -0,0 +1,199 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_ipac.h - definitions for the Siemens IPAC PSB2115 chip + * ========================================================== + * + * $Id: i4b_ipac.h,v 1.4 1998/12/05 18:04:39 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:23:50 1998] + * + *--------------------------------------------------------------------------- + */ + +#ifndef _I4B_IPAC_H_ +#define _I4B_IPAC_H_ + +#define IPAC_BFIFO_LEN 64 /* 64 bytes B-channel FIFO on chip */ + +#define IPAC_HSCXA_OFF 0x00 +#define IPAC_HSCXB_OFF 0x40 +#define IPAC_ISAC_OFF 0x80 +#define IPAC_IPAC_OFF 0xc0 + +/* + * definitions of registers and bits for the IPAC ISDN chip. + */ + +typedef struct ipac_reg { + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char ipac_conf; + unsigned char ipac_ista; + unsigned char ipac_id; + unsigned char ipac_acfg; + unsigned char ipac_aoe; + unsigned char ipac_arx; + unsigned char ipac_pita1; + unsigned char ipac_pita2; + unsigned char ipac_pota1; + unsigned char ipac_pota2; + unsigned char ipac_pcfg; + unsigned char ipac_scfg; + unsigned char ipac_timr2; + } ipac_r; + struct { + unsigned char ipac_conf; + unsigned char ipac_mask; + unsigned char ipac_dummy; + unsigned char ipac_acfg; + unsigned char ipac_aoe; + unsigned char ipac_atx; + unsigned char ipac_pita1; + unsigned char ipac_pita2; + unsigned char ipac_pota1; + unsigned char ipac_pota2; + unsigned char ipac_pcfg; + unsigned char ipac_scfg; + unsigned char ipac_timr2; + } ipac_w; + } ipac_rw; +} ipac_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* IPAC read registers */ + +#define IPAC_CONF REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_conf) +#define IPAC_ISTA REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_ista) +#define IPAC_ID REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_id) +#define IPAC_ACFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_acfg) +#define IPAC_AOE REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_aoe) +#define IPAC_ARX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_arx) +#define IPAC_PITA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita1) +#define IPAC_PITA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pita2) +#define IPAC_POTA1 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota1) +#define IPAC_POTA2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pota2) +#define IPAC_PCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_pcfg) +#define IPAC_SCFG REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_scfg) +#define IPAC_TIMR2 REG_OFFSET(ipac_reg_t, ipac_rw.ipac_r.ipac_timr2) + +/* IPAC write registers */ + +#define IPAC_MASK REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_mask) +#define IPAC_ATX REG_OFFSET(ipac_reg_t, ipac_rw.ipac_w.ipac_atx) + +/* register bits */ + +#define IPAC_CONF_AMP 0x80 +#define IPAC_CONF_CFS 0x40 +#define IPAC_CONF_TEM 0x20 +#define IPAC_CONF_PDS 0x10 +#define IPAC_CONF_IDH 0x08 +#define IPAC_CONF_SGO 0x04 +#define IPAC_CONF_ODS 0x02 +#define IPAC_CONF_IOF 0x01 + +#define IPAC_ISTA_INT1 0x80 +#define IPAC_ISTA_INT0 0x40 +#define IPAC_ISTA_ICD 0x20 +#define IPAC_ISTA_EXD 0x10 +#define IPAC_ISTA_ICA 0x08 +#define IPAC_ISTA_EXA 0x04 +#define IPAC_ISTA_ICB 0x02 +#define IPAC_ISTA_EXB 0x01 + +#define IPAC_MASK_INT1 0x80 +#define IPAC_MASK_INT0 0x40 +#define IPAC_MASK_ICD 0x20 +#define IPAC_MASK_EXD 0x10 +#define IPAC_MASK_ICA 0x08 +#define IPAC_MASK_EXA 0x04 +#define IPAC_MASK_ICB 0x02 +#define IPAC_MASK_EXB 0x01 + +#define IPAC_ACFG_OD7 0x80 +#define IPAC_ACFG_OD6 0x40 +#define IPAC_ACFG_OD5 0x20 +#define IPAC_ACFG_OD4 0x10 +#define IPAC_ACFG_OD3 0x08 +#define IPAC_ACFG_OD2 0x04 +#define IPAC_ACFG_EL1 0x02 +#define IPAC_ACFG_EL2 0x01 + +#define IPAC_AOE_OE7 0x80 +#define IPAC_AOE_OE6 0x40 +#define IPAC_AOE_OE5 0x20 +#define IPAC_AOE_OE4 0x10 +#define IPAC_AOE_OE3 0x08 +#define IPAC_AOE_OE2 0x04 + +#define IPAC_ARX_AR7 0x80 +#define IPAC_ARX_AR6 0x40 +#define IPAC_ARX_AR5 0x20 +#define IPAC_ARX_AR4 0x10 +#define IPAC_ARX_AR3 0x08 +#define IPAC_ARX_AR2 0x04 + +#define IPAC_ATX_AT7 0x80 +#define IPAC_ATX_AT6 0x40 +#define IPAC_ATX_AT5 0x20 +#define IPAC_ATX_AT4 0x10 +#define IPAC_ATX_AT3 0x08 +#define IPAC_ATX_AT2 0x04 + +#define IPAC_PITA1_ENA 0x80 +#define IPAC_PITA1_DUDD 0x40 + +#define IPAC_PITA2_ENA 0x80 +#define IPAC_PITA2_DUDD 0x40 + +#define IPAC_POTA1_ENA 0x80 +#define IPAC_POTA1_DUDD 0x40 + +#define IPAC_POTA2_ENA 0x80 +#define IPAC_POTA2_DUDD 0x40 + +#define IPAC_PCFG_DPS 0x80 +#define IPAC_PCFG_ACL 0x40 +#define IPAC_PCFG_LED 0x20 +#define IPAC_PCFG_PLD 0x10 +#define IPAC_PCFG_FBS 0x08 +#define IPAC_PCFG_CSL2 0x04 +#define IPAC_PCFG_CSL1 0x02 +#define IPAC_PCFG_CSL0 0x01 + +#define IPAC_SCFG_PRI 0x80 +#define IPAC_SCFG_TXD 0x40 +#define IPAC_SCFG_TLEN 0x20 + +#define IPAC_TIMR2_TMD 0x80 + +#endif /* _I4B_IPAC_H_ */ diff --git a/sys/i4b/layer1/i4b_isac.c b/sys/i4b/layer1/i4b_isac.c new file mode 100644 index 0000000..4065c9a --- /dev/null +++ b/sys/i4b/layer1/i4b_isac.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isac.c - i4b siemens isdn chipset driver ISAC handler + * --------------------------------------------------------- + * + * $Id: i4b_isac.c,v 1.28 1998/12/05 18:04:41 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:23:59 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#else +#define NISIC 1 /* non-FreeBSD handles this via config(8) */ +#endif +#if NISIC > 0 + +#ifdef __FreeBSD__ +#include "opt_i4b.h" +#endif +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <machine/stdarg.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +static u_char isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir); +static void isic_isac_ind_hdlr(register struct isic_softc *sc, int ind); + +/*---------------------------------------------------------------------------* + * ISAC interrupt service routine + *---------------------------------------------------------------------------*/ +void +isic_isac_irq(struct isic_softc *sc, int ista) +{ + register u_char c = 0; + DBGL1(L1_F_MSG, "isic_isac_irq", ("unit %d: ista = 0x%02x\n", sc->sc_unit, ista)); + + if(ista & ISAC_ISTA_EXI) /* extended interrupt */ + { + c |= isic_isac_exir_hdlr(sc, ISAC_READ(I_EXIR)); + } + + if(ista & ISAC_ISTA_RME) /* receive message end */ + { + register int rest; + u_char rsta; + + /* get rx status register */ + + rsta = ISAC_READ(I_RSTA); + + if((rsta & ISAC_RSTA_MASK) != 0x20) + { + int error = 0; + + if(!(rsta & ISAC_RSTA_CRC)) /* CRC error */ + { + error++; + DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: CRC error\n", sc->sc_unit)); + } + + if(rsta & ISAC_RSTA_RDO) /* ReceiveDataOverflow */ + { + error++; + DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Data Overrun error\n", sc->sc_unit)); + } + + if(rsta & ISAC_RSTA_RAB) /* ReceiveABorted */ + { + error++; + DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: Receive Aborted error\n", sc->sc_unit)); + } + + if(error == 0) + DBGL1(L1_I_ERR, "isic_isac_irq", ("unit %d: RME unknown error, RSTA = 0x%02x!\n", sc->sc_unit, rsta)); + + i4b_Dfreembuf(sc->sc_ibuf); + + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + ISAC_WRITE(I_CMDR, ISAC_CMDR_RMC|ISAC_CMDR_RRES); + ISACCMDRWRDELAY(); + + return; + } + + rest = (ISAC_READ(I_RBCL) & (ISAC_FIFO_LEN-1)); + + if(rest == 0) + rest = ISAC_FIFO_LEN; + + if(sc->sc_ibuf == NULL) + { + if((sc->sc_ibuf = i4b_Dgetmbuf(rest)) != NULL) + sc->sc_ib = sc->sc_ibuf->m_data; + else + panic("isic_isac_irq: RME, i4b_Dgetmbuf returns NULL!\n"); + sc->sc_ilen = 0; + } + + if(sc->sc_ilen <= (MAX_DFRAME_LEN - rest)) + { + ISAC_RDFIFO(sc->sc_ib, rest); + sc->sc_ilen += rest; + + sc->sc_ibuf->m_pkthdr.len = + sc->sc_ibuf->m_len = sc->sc_ilen; + + if(sc->sc_trace & TRACE_D_RX) + { + i4b_trace_hdr_t hdr; + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_D; + hdr.dir = FROM_NT; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, sc->sc_ibuf->m_len, sc->sc_ibuf->m_data); + } + + c |= ISAC_CMDR_RMC; + + if(sc->sc_enabled) + PH_Data_Ind(sc->sc_unit, sc->sc_ibuf); + else + i4b_Dfreembuf(sc->sc_ibuf); + } + else + { + DBGL1(L1_I_ERR, "isic_isac_irq", ("RME, input buffer overflow!\n")); + i4b_Dfreembuf(sc->sc_ibuf); + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + } + + if(ista & ISAC_ISTA_RPF) /* receive fifo full */ + { + if(sc->sc_ibuf == NULL) + { + if((sc->sc_ibuf = i4b_Dgetmbuf(MAX_DFRAME_LEN)) != NULL) + sc->sc_ib= sc->sc_ibuf->m_data; + else + panic("isic_isac_irq: RPF, i4b_Dgetmbuf returns NULL!\n"); + sc->sc_ilen = 0; + } + + if(sc->sc_ilen <= (MAX_DFRAME_LEN - ISAC_FIFO_LEN)) + { + ISAC_RDFIFO(sc->sc_ib, ISAC_FIFO_LEN); + sc->sc_ilen += ISAC_FIFO_LEN; + sc->sc_ib += ISAC_FIFO_LEN; + c |= ISAC_CMDR_RMC; + } + else + { + DBGL1(L1_I_ERR, "isic_isac_irq", ("RPF, input buffer overflow!\n")); + i4b_Dfreembuf(sc->sc_ibuf); + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + } + + if(ista & ISAC_ISTA_XPR) /* transmit fifo empty (XPR bit set) */ + { + if((sc->sc_obuf2 != NULL) && (sc->sc_obuf == NULL)) + { + sc->sc_freeflag = sc->sc_freeflag2; + sc->sc_obuf = sc->sc_obuf2; + sc->sc_op = sc->sc_obuf->m_data; + sc->sc_ol = sc->sc_obuf->m_len; + sc->sc_obuf2 = NULL; +#ifdef NOTDEF + printf("ob2=%x, op=%x, ol=%d, f=%d #", + sc->sc_obuf, + sc->sc_op, + sc->sc_ol, + sc->sc_state); +#endif + } + else + { +#ifdef NOTDEF + printf("ob=%x, op=%x, ol=%d, f=%d #", + sc->sc_obuf, + sc->sc_op, + sc->sc_ol, + sc->sc_state); +#endif + } + + if(sc->sc_obuf) + { + ISAC_WRFIFO(sc->sc_op, min(sc->sc_ol, ISAC_FIFO_LEN)); + + if(sc->sc_ol > ISAC_FIFO_LEN) /* length > 32 ? */ + { + sc->sc_op += ISAC_FIFO_LEN; /* bufferptr+32 */ + sc->sc_ol -= ISAC_FIFO_LEN; /* length - 32 */ + c |= ISAC_CMDR_XTF; /* set XTF bit */ + } + else + { + if(sc->sc_freeflag) + { + i4b_Dfreembuf(sc->sc_obuf); + sc->sc_freeflag = 0; + } + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + + c |= ISAC_CMDR_XTF | ISAC_CMDR_XME; + } + } + else + { + sc->sc_state &= ~ISAC_TX_ACTIVE; + } + } + + if(ista & ISAC_ISTA_CISQ) /* channel status change CISQ */ + { + register u_char ci; + + /* get command/indication rx register*/ + + ci = ISAC_READ(I_CIRR); + + /* if S/Q IRQ, read SQC reg to clr SQC IRQ */ + + if(ci & ISAC_CIRR_SQC) + (void) ISAC_READ(I_SQRR); + + /* C/I code change IRQ (flag already cleared by CIRR read) */ + + if(ci & ISAC_CIRR_CIC0) + isic_isac_ind_hdlr(sc, (ci >> 2) & 0xf); + } + + if(c) + { + ISAC_WRITE(I_CMDR, c); + ISACCMDRWRDELAY(); + } +} + +/*---------------------------------------------------------------------------* + * ISAC L1 Extended IRQ handler + *---------------------------------------------------------------------------*/ +static u_char +isic_isac_exir_hdlr(register struct isic_softc *sc, u_char exir) +{ + u_char c = 0; + + if(exir & ISAC_EXIR_XMR) + { + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Message Repeat\n")); + + c |= ISAC_CMDR_XRES; + } + + if(exir & ISAC_EXIR_XDU) + { + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Tx Data Underrun\n")); + + c |= ISAC_CMDR_XRES; + } + + if(exir & ISAC_EXIR_PCE) + { + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Protocol Error\n")); + } + + if(exir & ISAC_EXIR_RFO) + { + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Rx Frame Overflow\n")); + + c |= ISAC_CMDR_RMC|ISAC_CMDR_RRES; + } + + if(exir & ISAC_EXIR_SOV) + { + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Sync Xfer Overflow\n")); + } + + if(exir & ISAC_EXIR_MOS) + { + DBGL1(L1_I_ERR, "L1 isic_isac_exir_hdlr", ("EXIRQ Monitor Status\n")); + } + + if(exir & ISAC_EXIR_SAW) + { + /* cannot happen, STCR:TSF is set to 0 */ + + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Subscriber Awake\n")); + } + + if(exir & ISAC_EXIR_WOV) + { + /* cannot happen, STCR:TSF is set to 0 */ + + DBGL1(L1_I_ERR, "isic_isac_exir_hdlr", ("EXIRQ Watchdog Timer Overflow\n")); + } + + return(c); +} + +/*---------------------------------------------------------------------------* + * ISAC L1 Indication handler + *---------------------------------------------------------------------------*/ +static void +isic_isac_ind_hdlr(register struct isic_softc *sc, int ind) +{ + register int event; + + switch(ind) + { + case ISAC_CIRR_IAI8: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI8 in state %s\n", isic_printstate(sc))); + if(sc->sc_bustyp == BUS_TYPE_IOM2) + isic_isac_l1_cmd(sc, CMD_AR8); + event = EV_INFO48; + MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE); + break; + + case ISAC_CIRR_IAI10: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx AI10 in state %s\n", isic_printstate(sc))); + if(sc->sc_bustyp == BUS_TYPE_IOM2) + isic_isac_l1_cmd(sc, CMD_AR10); + event = EV_INFO410; + MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_ACTIVE); + break; + + case ISAC_CIRR_IRSY: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx RSY in state %s\n", isic_printstate(sc))); + event = EV_RSY; + break; + + case ISAC_CIRR_IPU: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx PU in state %s\n", isic_printstate(sc))); + event = EV_PU; + break; + + case ISAC_CIRR_IDR: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DR in state %s\n", isic_printstate(sc))); + isic_isac_l1_cmd(sc, CMD_DIU); + event = EV_DR; + break; + + case ISAC_CIRR_IDID: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DID in state %s\n", isic_printstate(sc))); + event = EV_INFO0; + MPH_Status_Ind(sc->sc_unit, STI_L1STAT, LAYER_IDLE); + break; + + case ISAC_CIRR_IDIS: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx DIS in state %s\n", isic_printstate(sc))); + event = EV_DIS; + break; + + case ISAC_CIRR_IEI: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx EI in state %s\n", isic_printstate(sc))); + isic_isac_l1_cmd(sc, CMD_DIU); + event = EV_EI; + break; + + case ISAC_CIRR_IARD: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ARD in state %s\n", isic_printstate(sc))); + event = EV_INFO2; + break; + + case ISAC_CIRR_ITI: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx TI in state %s\n", isic_printstate(sc))); + event = EV_INFO0; + break; + + case ISAC_CIRR_IATI: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx ATI in state %s\n", isic_printstate(sc))); + event = EV_INFO0; + break; + + case ISAC_CIRR_ISD: + DBGL1(L1_I_CICO, "isic_isac_ind_hdlr", ("rx SD in state %s\n", isic_printstate(sc))); + event = EV_INFO0; + break; + + default: + DBGL1(L1_I_ERR, "isic_isac_ind_hdlr", ("UNKNOWN Indication 0x%x in state %s\n", ind, isic_printstate(sc))); + event = EV_INFO0; + break; + } + isic_next_state(sc, event); +} + +/*---------------------------------------------------------------------------* + * execute a layer 1 command + *---------------------------------------------------------------------------*/ +void +isic_isac_l1_cmd(struct isic_softc *sc, int command) +{ + u_char cmd; + +#ifdef I4B_SMP_WORKAROUND + + /* XXXXXXXXXXXXXXXXXXX */ + + /* + * patch from Wolfgang Helbig: + * + * Here is a patch that makes i4b work on an SMP: + * The card (TELES 16.3) didn't interrupt on an SMP machine. + * This is a gross workaround, but anyway it works *and* provides + * some information as how to finally fix this problem. + */ + + HSCX_WRITE(0, H_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + ISAC_WRITE(I_MASK, 0xff); + DELAY(100); + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + ISAC_WRITE(I_MASK, ISAC_IMASK); + + /* XXXXXXXXXXXXXXXXXXX */ + +#endif /* I4B_SMP_WORKAROUND */ + + if(command < 0 || command > CMD_ILL) + { + DBGL1(L1_I_ERR, "isic_isac_l1_cmd", ("illegal cmd 0x%x in state %s\n", command, isic_printstate(sc))); + return; + } + + if(sc->sc_bustyp == BUS_TYPE_IOM2) + cmd = ISAC_CIX0_LOW; + else + cmd = 0; + + switch(command) + { + case CMD_TIM: + DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx TIM in state %s\n", isic_printstate(sc))); + cmd |= (ISAC_CIXR_CTIM << 2); + break; + + case CMD_RS: + DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx RS in state %s\n", isic_printstate(sc))); + cmd |= (ISAC_CIXR_CRS << 2); + break; + + case CMD_AR8: + DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR8 in state %s\n", isic_printstate(sc))); + cmd |= (ISAC_CIXR_CAR8 << 2); + break; + + case CMD_AR10: + DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx AR10 in state %s\n", isic_printstate(sc))); + cmd |= (ISAC_CIXR_CAR10 << 2); + break; + + case CMD_DIU: + DBGL1(L1_I_CICO, "isic_isac_l1_cmd", ("tx DIU in state %s\n", isic_printstate(sc))); + cmd |= (ISAC_CIXR_CDIU << 2); + break; + } + ISAC_WRITE(I_CIXR, cmd); +} + +/*---------------------------------------------------------------------------* + * L1 ISAC initialization + *---------------------------------------------------------------------------*/ +int +isic_isac_init(struct isic_softc *sc) +{ + ISAC_IMASK = 0xff; /* disable all irqs */ + + ISAC_WRITE(I_MASK, ISAC_IMASK); + + if(sc->sc_bustyp != BUS_TYPE_IOM2) + { + DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-1 mode\n")); + + /* ADF2: Select mode IOM-1 */ + ISAC_WRITE(I_ADF2, 0x00); + + /* SPCR: serial port control register: + * SPU - software power up = 0 + * SAC - SIP port high Z + * SPM - timing mode 0 + * TLP - test loop = 0 + * C1C, C2C - B1 and B2 switched to/from SPa + */ + ISAC_WRITE(I_SPCR, ISAC_SPCR_C1C1|ISAC_SPCR_C2C1); + + /* SQXR: S/Q channel xmit register: + * SQIE - S/Q IRQ enable = 0 + * SQX1-4 - Fa bits = 1 + */ + ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4); + + /* ADF1: additional feature reg 1: + * WTC - watchdog = 0 + * TEM - test mode = 0 + * PFS - pre-filter = 0 + * CFS - IOM clock/frame always active + * FSC1/2 - polarity of 8kHz strobe + * ITF - interframe fill = idle + */ + ISAC_WRITE(I_ADF1, ISAC_ADF1_FC2); /* ADF1 */ + + /* STCR: sync transfer control reg: + * TSF - terminal secific functions = 0 + * TBA - TIC bus address = 7 + * STx/SCx = 0 + */ + ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0); + + /* MODE: Mode Register: + * MDSx - transparent mode 2 + * TMD - timer mode = external + * RAC - Receiver enabled + * DIMx - digital i/f mode + */ + ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0); + } + else + { + DBGL1(L1_I_SETUP, "isic_isac_setup", ("configuring for IOM-2 mode\n")); + + /* ADF2: Select mode IOM-2 */ + ISAC_WRITE(I_ADF2, ISAC_ADF2_IMS); + + /* SPCR: serial port control register: + * SPU - software power up = 0 + * SPM - timing mode 0 + * TLP - test loop = 0 + * C1C, C2C - B1 + C1 and B2 + IC2 monitoring + */ + ISAC_WRITE(I_SPCR, 0x00); + + /* SQXR: S/Q channel xmit register: + * IDC - IOM direction = 0 (master) + * CFS - Config Select = 0 (clock always active) + * CI1E - C/I channel 1 IRQ enable = 0 + * SQIE - S/Q IRQ enable = 0 + * SQX1-4 - Fa bits = 1 + */ + ISAC_WRITE(I_SQXR, ISAC_SQXR_SQX1|ISAC_SQXR_SQX2|ISAC_SQXR_SQX3|ISAC_SQXR_SQX4); + + /* ADF1: additional feature reg 1: + * WTC - watchdog = 0 + * TEM - test mode = 0 + * PFS - pre-filter = 0 + * IOF - IOM i/f off = 0 + * ITF - interframe fill = idle + */ + ISAC_WRITE(I_ADF1, 0x00); + + /* STCR: sync transfer control reg: + * TSF - terminal secific functions = 0 + * TBA - TIC bus address = 7 + * STx/SCx = 0 + */ + ISAC_WRITE(I_STCR, ISAC_STCR_TBA2|ISAC_STCR_TBA1|ISAC_STCR_TBA0); + + /* MODE: Mode Register: + * MDSx - transparent mode 2 + * TMD - timer mode = external + * RAC - Receiver enabled + * DIMx - digital i/f mode + */ + ISAC_WRITE(I_MODE, ISAC_MODE_MDS2|ISAC_MODE_MDS1|ISAC_MODE_RAC|ISAC_MODE_DIM0); + } + +#ifdef NOTDEF + /* + * XXX a transmitter reset causes an ISAC tx IRQ which will not + * be serviced at attach time under some circumstances leaving + * the associated IRQ line on the ISA bus active. This prevents + * any further interrupts to be serviced because no low -> high + * transition can take place anymore. (-hm) + */ + + /* command register: + * RRES - HDLC receiver reset + * XRES - transmitter reset + */ + ISAC_WRITE(I_CMDR, ISAC_CMDR_RRES|ISAC_CMDR_XRES); + ISACCMDRWRDELAY(); +#endif + + /* enabled interrupts: + * =================== + * RME - receive message end + * RPF - receive pool full + * XPR - transmit pool ready + * CISQ - CI or S/Q channel change + * EXI - extended interrupt + */ + + ISAC_IMASK = ISAC_MASK_RSC | /* auto mode only */ + ISAC_MASK_TIN | /* timer irq */ + ISAC_MASK_SIN; /* sync xfer irq */ + + ISAC_WRITE(I_MASK, ISAC_IMASK); + + return(0); +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_isac.h b/sys/i4b/layer1/i4b_isac.h new file mode 100644 index 0000000..56a4241 --- /dev/null +++ b/sys/i4b/layer1/i4b_isac.h @@ -0,0 +1,391 @@ +/* + * Copyright (c) 1996, 1998 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * $Id: i4b_isac.h,v 1.5 1998/03/28 15:11:03 hm Exp $ + * + * last edit-date: [Fri Mar 27 15:52:40 1998] + * + * -hm split up for rewrite of Siemens chipset driver + * + *--------------------------------------------------------------------------- + */ + +#ifndef I4B_ISAC_H_ +#define I4B_ISAC_H_ + +/* + * The ISAC databook specifies a delay of 2.5 DCL clock cycles between + * writes to the ISAC command register CMDR. This is the delay used to + * satisfy this requirement. + */ + +#define I4B_ISAC_CMDRWRDELAY 30 + +#if (I4B_ISAC_CMDRWRDELAY > 0) +#define ISACCMDRWRDELAY() DELAY(I4B_ISAC_CMDRWRDELAY) +#else +#warning "I4B_ISAC_CMDRWRDELAY set to 0!" +#define ISACCMDRWRDELAY() +#endif + +enum ISAC_VERSIONS { + ISAC_VA, /* 2085 A1 or A2, 2086/2186 V1.1 */ + ISAC_VB1, /* 2085 B1 */ + ISAC_VB2, /* 2085 B2 */ + ISAC_VB3, /* 2085 B3/V2.3 */ + ISAC_UNKN /* unknown version */ +}; + +#define ISAC_FIFO_LEN 32 /* 32 bytes FIFO on chip */ + +/* + * definitions of registers and bits for the ISAC ISDN chip. + */ + +typedef struct isac_reg { + + /* 32 byte deep FIFO always first */ + + unsigned char isac_fifo [ISAC_FIFO_LEN]; + + /* most registers can be read/written, but have different names */ + /* so define a union with read/write names to make that clear */ + + union { + struct { + unsigned char isac_ista; + unsigned char isac_star; + unsigned char isac_mode; + unsigned char isac_timr; + unsigned char isac_exir; + unsigned char isac_rbcl; + unsigned char isac_sapr; + unsigned char isac_rsta; + unsigned char dummy_28; + unsigned char isac_rhcr; + unsigned char isac_rbch; + unsigned char isac_star2; + unsigned char dummy_2c; + unsigned char dummy_2d; + unsigned char dummy_2e; + unsigned char dummt_2f; + unsigned char isac_spcr; + unsigned char isac_cirr; + unsigned char isac_mor; + unsigned char isac_sscr; + unsigned char isac_sfcr; + unsigned char isac_c1r; + unsigned char isac_c2r; + unsigned char isac_b1cr; + unsigned char isac_b2cr; + unsigned char isac_adf2; + unsigned char isac_mosr; + unsigned char isac_sqrr; + } isac_r; + struct { + unsigned char isac_mask; + unsigned char isac_cmdr; + unsigned char isac_mode; + unsigned char isac_timr; + unsigned char isac_xad1; + unsigned char isac_xad2; + unsigned char isac_sap1; + unsigned char isac_sap2; + unsigned char isac_tei1; + unsigned char isac_tei2; + unsigned char dummy_2a; + unsigned char isac_star2; + unsigned char dummy_2c; + unsigned char dummy_2d; + unsigned char dummy_2e; + unsigned char dummt_2f; + unsigned char isac_spcr; + unsigned char isac_cixr; + unsigned char isac_mox; + unsigned char isac_sscx; + unsigned char isac_sfcw; + unsigned char isac_c1r; + unsigned char isac_c2r; + unsigned char isac_stcr; + unsigned char isac_adf1; + unsigned char isac_adf2; + unsigned char isac_mocr; + unsigned char isac_sqxr; + } isac_w; + } isac_rw; +} isac_reg_t; + +#define REG_OFFSET(type, field) (int)(&(((type *)0)->field)) + +/* ISAC read registers */ + +#define i_ista isac_rw.isac_r.isac_ista +#define I_ISTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_ista) +#define i_star isac_rw.isac_r.isac_star +#define I_STAR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star) +#define i_mode isac_rw.isac_r.isac_mode +#define I_MODE REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mode) +#define i_timr isac_rw.isac_r.isac_timr +#define I_TIMR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_timr) +#define i_exir isac_rw.isac_r.isac_exir +#define I_EXIR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_exir) +#define i_rbcl isac_rw.isac_r.isac_rbcl +#define I_RBCL REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbcl) +#define i_sapr isac_rw.isac_r.isac_sapr +#define I_SAPR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sapr) +#define i_rsta isac_rw.isac_r.isac_rsta +#define I_RSTA REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rsta) +#define i_rhcr isac_rw.isac_r.isac_rhcr +#define I_RHCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rhcr) +#define i_rbch isac_rw.isac_r.isac_rbch +#define I_RBCH REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_rbch) +#define i_star2 isac_rw.isac_r.isac_star2 +#define I_STAR2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_star2) +#define i_spcr isac_rw.isac_r.isac_spcr +#define I_SPCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_spcr) +#define i_cirr isac_rw.isac_r.isac_cirr +#define I_CIRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_cirr) +#define i_mor isac_rw.isac_r.isac_mor +#define I_MOR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mor) +#define i_sscr isac_rw.isac_r.isac_sscr +#define I_SSCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sscr) +#define i_sfcr isac_rw.isac_r.isac_sfcr +#define I_SFCR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sfcr) +#define i_c1r isac_rw.isac_r.isac_c1r +#define I_C1R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c1r) +#define i_c2r isac_rw.isac_r.isac_c2r +#define I_C2R REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_c2r) +#define i_b1cr isac_rw.isac_r.isac_b1cr +#define I_B1CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b1cr) +#define i_b2cr isac_rw.isac_r.isac_b2cr +#define I_B2CR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_b2cr) +#define i_adf2 isac_rw.isac_r.isac_adf2 +#define I_ADF2 REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_adf2) +#define i_mosr isac_rw.isac_r.isac_mosr +#define I_MOSR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_mosr) +#define i_sqrr isac_rw.isac_r.isac_sqrr +#define I_SQRR REG_OFFSET(isac_reg_t, isac_rw.isac_r.isac_sqrr) + +/* ISAC write registers - isac_mode, isac_timr, isac_star2, isac_spcr, */ +/* isac_c1r, isac_c2r, isac_adf2 see read registers */ + +#define i_mask isac_rw.isac_w.isac_mask +#define I_MASK REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mask) +#define i_cmdr isac_rw.isac_w.isac_cmdr +#define I_CMDR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cmdr) +#define i_xad1 isac_rw.isac_w.isac_xad1 +#define I_XAD1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad1) +#define i_xad2 isac_rw.isac_w.isac_xad2 +#define I_XAD2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_xad2) +#define i_sap1 isac_rw.isac_w.isac_sap1 +#define I_SAP1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap1) +#define i_sap2 isac_rw.isac_w.isac_sap2 +#define I_SAP2 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sap2) +#define i_tei1 isac_rw.isac_w.isac_tei1 +#define i_tei2 isac_rw.isac_w.isac_tei2 +#define i_cixr isac_rw.isac_w.isac_cixr +#define I_CIXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_cixr) +#define I_CIX0 I_CIXR +#define i_mox isac_rw.isac_w.isac_mox +#define I_MOX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mox) +#define i_sscx isac_rw.isac_w.isac_sscx +#define I_SSCX REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sscx) +#define i_sfcw isac_rw.isac_w.isac_sfcw +#define I_SFCW REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sfcw) +#define i_stcr isac_rw.isac_w.isac_stcr +#define I_STCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_stcr) +#define i_adf1 isac_rw.isac_w.isac_adf1 +#define I_ADF1 REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_adf1) +#define i_mocr isac_rw.isac_w.isac_mocr +#define I_MOCR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_mocr) +#define i_sqxr isac_rw.isac_w.isac_sqxr +#define I_SQXR REG_OFFSET(isac_reg_t, isac_rw.isac_w.isac_sqxr) + +#define ISAC_ISTA_RME 0x80 +#define ISAC_ISTA_RPF 0x40 +#define ISAC_ISTA_RSC 0x20 +#define ISAC_ISTA_XPR 0x10 +#define ISAC_ISTA_TIN 0x08 +#define ISAC_ISTA_CISQ 0x04 +#define ISAC_ISTA_SIN 0x02 +#define ISAC_ISTA_EXI 0x01 + +#define ISAC_MASK_RME 0x80 +#define ISAC_MASL_RPF 0x40 +#define ISAC_MASK_RSC 0x20 +#define ISAC_MASK_XPR 0x10 +#define ISAC_MASK_TIN 0x08 +#define ISAC_MASK_CISQ 0x04 +#define ISAC_MASK_SIN 0x02 +#define ISAC_MASK_EXI 0x01 +#define ISAC_MASK_ALL 0xff + +#define ISAC_STAR_XDOV 0x80 +#define ISAC_STAR_XFW 0x40 +#define ISAC_STAR_XRNR 0x20 +#define ISAC_STAR_RRNR 0x10 +#define ISAC_STAR_MBR 0x08 +#define ISAC_STAR_MAC1 0x04 +#define ISAC_STAR_BVS 0x02 +#define ISAC_STAR_MAC0 0x01 + +#define ISAC_CMDR_RMC 0x80 +#define ISAC_CMDR_RRES 0x40 +#define ISAC_CMDR_RNR 0x20 +#define ISAC_CMDR_STI 0x10 +#define ISAC_CMDR_XTF 0x08 +#define ISAC_CMDR_XIF 0x04 +#define ISAC_CMDR_XME 0x02 +#define ISAC_CMDR_XRES 0x01 + +#define ISAC_MODE_MDS2 0x80 +#define ISAC_MODE_MDS1 0x40 +#define ISAC_MODE_MDS0 0x20 +#define ISAC_MODE_TMD 0x10 +#define ISAC_MODE_RAC 0x08 +#define ISAC_MODE_DIM2 0x04 +#define ISAC_MODE_DIM1 0x02 +#define ISAC_MODE_DIM0 0x01 + +#define ISAC_EXIR_XMR 0x80 +#define ISAC_EXIR_XDU 0x40 +#define ISAC_EXIR_PCE 0x20 +#define ISAC_EXIR_RFO 0x10 +#define ISAC_EXIR_SOV 0x08 +#define ISAC_EXIR_MOS 0x04 +#define ISAC_EXIR_SAW 0x02 +#define ISAC_EXIR_WOV 0x01 + +#define ISAC_RSTA_RDA 0x80 +#define ISAC_RSTA_RDO 0x40 +#define ISAC_RSTA_CRC 0x20 +#define ISAC_RSTA_RAB 0x10 +#define ISAC_RSTA_SA1 0x08 +#define ISAC_RSTA_SA0 0x04 +#define ISAC_RSTA_CR 0x02 +#define ISAC_RSTA_TA 0x01 + +#define ISAC_RSTA_MASK 0x70 /* the interesting bits */ + +#define ISAC_RBCH_XAC 0x80 +#define ISAC_RBCH_VN1 0x40 +#define ISAC_RBCH_VN0 0x20 +#define ISAC_RBCH_OV 0x10 +/* the other 4 bits are the high bits of the receive byte count */ + +#define ISAC_SPCR_SPU 0x80 +#define ISAC_SPCR_SAC 0x40 +#define ISAC_SPCR_SPM 0x20 +#define ISAC_SPCR_TLP 0x10 +#define ISAC_SPCR_C1C1 0x08 +#define ISAC_SPCR_C1C0 0x04 +#define ISAC_SPCR_C2C1 0x02 +#define ISAC_SPCR_C2C0 0x01 + +#define ISAC_CIRR_SQC 0x80 +#define ISAC_CIRR_BAS 0x40 +/* bits 5-2 CODR */ +#define ISAC_CIRR_CIC0 0x02 +/* bit 0 is always 0 */ +/* C/I codes from bits 5-2 (>> 2 & 0xf) */ +/* the indications */ +#define ISAC_CIRR_IPU 0x07 +#define ISAC_CIRR_IDR 0x00 +#define ISAC_CIRR_ISD 0x02 +#define ISAC_CIRR_IDIS 0x03 +#define ISAC_CIRR_IEI 0x06 +#define ISAC_CIRR_IRSY 0x04 +#define ISAC_CIRR_IARD 0x08 +#define ISAC_CIRR_ITI 0x0a +#define ISAC_CIRR_IATI 0x0b +#define ISAC_CIRR_IAI8 0x0c +#define ISAC_CIRR_IAI10 0x0d +#define ISAC_CIRR_IDID 0x0f + +#define ISAC_CI_MASK 0x0f + +#define ISAC_CIXR_RSS 0x80 +#define ISAC_CIXR_BAC 0x40 +/* bits 5-2 CODX */ +#define ISAC_CIXR_TCX 0x02 +#define ISAC_CIXR_ECX 0x01 +/* in IOM-2 mode the low bits are always 1 */ +#define ISAC_CIX0_LOW 0x03 +/* C/I codes from bits 5-2 (>> 2 & 0xf) */ +/* the commands */ +#define ISAC_CIXR_CTIM 0 +#define ISAC_CIXR_CRS 0x01 +#define ISAC_CIXR_CSCZ 0x04 +#define ISAC_CIXR_CSSZ 0x02 +#define ISAC_CIXR_CAR8 0x08 +#define ISAC_CIXR_CAR10 0x09 +#define ISAC_CIXR_CARL 0x0a +#define ISAC_CIXR_CDIU 0x0f + +#define ISAC_STCR_TSF 0x80 +#define ISAC_STCR_TBA2 0x40 +#define ISAC_STCR_TBA1 0x20 +#define ISAC_STCR_TBA0 0x10 +#define ISAC_STCR_ST1 0x08 +#define ISAC_STCR_ST0 0x04 +#define ISAC_STCR_SC1 0x02 +#define ISAC_STCR_SC0 0x01 + +#define ISAC_ADF1_WTC1 0x80 +#define ISAC_ADF1_WTC2 0x40 +#define ISAC_ADF1_TEM 0x20 +#define ISAC_ADF1_PFS 0x10 +#define ISAC_ADF1_CFS 0x08 +#define ISAC_ADF1_FC2 0x04 +#define ISAC_ADF1_FC1 0x02 +#define ISAC_ADF1_ITF 0x01 + +#define ISAC_ADF2_IMS 0x80 +/* all other bits are 0 */ + +/* bits 7-5 are always 0 */ +#define ISAC_SQRR_SYN 0x10 +#define ISAC_SQRR_SQR1 0x08 +#define ISAC_SQRR_SQR2 0x04 +#define ISAC_SQRR_SQR3 0x02 +#define ISAC_SQRR_SQR4 0x01 + +#define ISAC_SQXR_IDC 0x80 +#define ISAC_SQXR_CFS 0x40 +#define ISAC_SQXR_CI1E 0x20 +#define ISAC_SQXR_SQIE 0x10 +#define ISAC_SQXR_SQX1 0x08 +#define ISAC_SQXR_SQX2 0x04 +#define ISAC_SQXR_SQX3 0x02 +#define ISAC_SQXR_SQX4 0x01 + +#endif /* I4B_ISAC_H_ */ diff --git a/sys/i4b/layer1/i4b_isic.c b/sys/i4b/layer1/i4b_isic.c new file mode 100644 index 0000000..922df79 --- /dev/null +++ b/sys/i4b/layer1/i4b_isic.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic.c - global isic stuff + * ============================== + * + * $Id: i4b_isic.c,v 1.44 1998/12/20 11:07:59 hm Exp $ + * + * last edit-date: [Fri Dec 18 12:14:07 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <sys/device.h> +#if defined(__NetBSD__) && defined(amiga) +#include <machine/bus.h> +#else +#include <dev/isa/isavar.h> +#endif +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +void isic_settrace(int unit, int val); +int isic_gettrace(int unit); + +#ifdef __FreeBSD__ +void isicintr_sc(struct isic_softc *sc); +#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006) +void isicintr(int unit); +#endif +#else +/* XXX - hack, going away soon! */ +struct isic_softc *isic_sc[ISIC_MAXUNIT]; +#endif + +/*---------------------------------------------------------------------------* + * isic - device driver interrupt routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +void +isicintr_sc(struct isic_softc *sc) +{ + isicintr(sc->sc_unit); +} + +void +isicintr(int unit) +{ + register struct isic_softc *sc = &isic_sc[unit]; +#else +int +isicintr(void *arg) +{ + struct isic_softc *sc = arg; +#endif + + if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */ + { + u_char was_hscx_irq = 0; + u_char was_isac_irq = 0; + + register u_char hscx_irq_stat; + register u_char isac_irq_stat; + + for(;;) + { + /* get hscx irq status from hscx b ista */ + hscx_irq_stat = + HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK; + + /* get isac irq status */ + isac_irq_stat = ISAC_READ(I_ISTA); + + /* do as long as there are pending irqs in the chips */ + if(!hscx_irq_stat && !isac_irq_stat) + break; + + if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF | + HSCX_ISTA_RSC | HSCX_ISTA_XPR | + HSCX_ISTA_TIN | HSCX_ISTA_EXB)) + { + isic_hscx_irq(sc, hscx_irq_stat, + HSCX_CH_B, + hscx_irq_stat & HSCX_ISTA_EXB); + was_hscx_irq = 1; + } + + if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA)) + { + isic_hscx_irq(sc, + HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK, + HSCX_CH_A, + hscx_irq_stat & HSCX_ISTA_EXA); + was_hscx_irq = 1; + } + + if(isac_irq_stat) + { + isic_isac_irq(sc, isac_irq_stat); /* isac handler */ + was_isac_irq = 1; + } + } +#ifndef amiga /* XXX should be: #if INTERUPTS_ARE_SHARED */ +#ifdef ELSA_QS1ISA + if(sc->sc_cardtyp != CARD_TYPEP_ELSAQS1ISA) + { +#endif + if((was_hscx_irq == 0) && (was_isac_irq == 0)) + DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from HSCX/ISAC!\n", sc->sc_unit)); +#ifdef ELSA_QS1ISA + } +#endif +#endif /* AMIGA */ + + HSCX_WRITE(0, H_MASK, 0xff); + ISAC_WRITE(I_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + +#ifdef ELSA_QS1ISA + DELAY(80); + + if(sc->sc_cardtyp == CARD_TYPEP_ELSAQS1ISA) + if (sc->clearirq) + { + sc->clearirq(sc); + } +#else + DELAY(100); +#endif + + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + ISAC_WRITE(I_MASK, ISAC_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); +#ifndef __FreeBSD__ + return(was_hscx_irq || was_isac_irq); +#endif + } + else /* IPAC interrupt routine */ + { + register u_char ipac_irq_stat; + register u_char was_ipac_irq = 0; + + for(;;) + { + /* get global irq status */ + + ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f; + + /* check hscx a */ + + if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA)) + { + /* HSCX A interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA), + HSCX_CH_A, + ipac_irq_stat & IPAC_ISTA_EXA); + was_ipac_irq = 1; + } + if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB)) + { + /* HSCX B interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA), + HSCX_CH_B, + ipac_irq_stat & IPAC_ISTA_EXB); + was_ipac_irq = 1; + } + if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD)) + { + /* ISAC interrupt */ + isic_isac_irq(sc, ISAC_READ(I_ISTA)); + was_ipac_irq = 1; + } + + /* do as long as there are pending irqs in the chip */ + if(!ipac_irq_stat) + break; + } + + if(was_ipac_irq == 0) + DBGL1(L1_ERROR, "isicintr", ("WARNING: unit %d, No IRQ from IPAC!\n", sc->sc_unit)); + + IPAC_WRITE(IPAC_MASK, 0xff); + DELAY(50); + IPAC_WRITE(IPAC_MASK, 0xc0); + +#ifndef __FreeBSD__ + return(was_ipac_irq); +#endif + } +} + +/*---------------------------------------------------------------------------* + * isic_settrace + *---------------------------------------------------------------------------*/ +void +isic_settrace(int unit, int val) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + sc->sc_trace = val; +} + +/*---------------------------------------------------------------------------* + * isic_gettrace + *---------------------------------------------------------------------------*/ +int +isic_gettrace(int unit) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + return(sc->sc_trace); +} + +/*---------------------------------------------------------------------------* + * isic_recovery - try to recover from irq lockup + *---------------------------------------------------------------------------*/ +void +isic_recover(struct isic_softc *sc) +{ + u_char byte; + + /* get hscx irq status from hscx b ista */ + + byte = HSCX_READ(HSCX_CH_B, H_ISTA); + + DBGL1(L1_ERROR, "isic_recover", ("HSCX B: ISTA = 0x%x\n", byte)); + + if(byte & HSCX_ISTA_ICA) + DBGL1(L1_ERROR, "isic_recover", ("HSCX A: ISTA = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_ISTA))); + + if(byte & HSCX_ISTA_EXB) + DBGL1(L1_ERROR, "isic_recover", ("HSCX B: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_B, H_EXIR))); + + if(byte & HSCX_ISTA_EXA) + DBGL1(L1_ERROR, "isic_recover", ("HSCX A: EXIR = 0x%x\n", (u_char)HSCX_READ(HSCX_CH_A, H_EXIR))); + + /* get isac irq status */ + + byte = ISAC_READ(I_ISTA); + + DBGL1(L1_ERROR, "isic_recover", (" ISAC: ISTA = 0x%x\n", byte)); + + if(byte & ISAC_ISTA_EXI) + DBGL1(L1_ERROR, "isic_recover", (" ISAC: EXIR = 0x%x\n", (u_char)ISAC_READ(I_EXIR))); + + if(byte & ISAC_ISTA_CISQ) + { + byte = ISAC_READ(I_CIRR); + + DBGL1(L1_ERROR, "isic_recover", (" ISAC: CISQ = 0x%x\n", byte)); + + if(byte & ISAC_CIRR_SQC) + DBGL1(L1_ERROR, "isic_recover", (" ISAC: SQRR = 0x%x\n", (u_char)ISAC_READ(I_SQRR))); + } + + DBGL1(L1_ERROR, "isic_recover", ("HSCX B: IMASK = 0x%x\n", HSCX_B_IMASK)); + DBGL1(L1_ERROR, "isic_recover", ("HSCX A: IMASK = 0x%x\n", HSCX_A_IMASK)); + + HSCX_WRITE(0, H_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + DELAY(100); + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + DELAY(100); + + DBGL1(L1_ERROR, "isic_recover", (" ISAC: IMASK = 0x%x\n", ISAC_IMASK)); + + ISAC_WRITE(I_MASK, 0xff); + DELAY(100); + ISAC_WRITE(I_MASK, ISAC_IMASK); +} + +#endif /* NISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_isic_isa.c b/sys/i4b/layer1/i4b_isic_isa.c new file mode 100644 index 0000000..c0e11b9 --- /dev/null +++ b/sys/i4b/layer1/i4b_isic_isa.c @@ -0,0 +1,591 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_isa.c - ISA bus interface + * ================================== + * + * $Id: i4b_isic_isa.c,v 1.14 1998/12/20 11:07:59 hm Exp $ + * + * last edit-date: [Fri Dec 18 12:00:26 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <sys/device.h> +#if defined(__NetBSD__) && defined(amiga) +#include <machine/bus.h> +#else +#include <dev/isa/isavar.h> +#endif +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#ifdef __FreeBSD__ + +#if !(defined(__FreeBSD_version)) || (defined(__FreeBSD_version) && __FreeBSD_version >= 300006) +void isicintr ( int unit ); +#endif + +void isicintr_sc(struct isic_softc *sc); + +static int isicprobe(struct isa_device *dev); +int isicattach(struct isa_device *dev); + +struct isa_driver isicdriver = { + isicprobe, + isicattach, + "isic", + 0 +}; + +int next_isic_unit = 0; +struct isic_softc isic_sc[ISIC_MAXUNIT]; + +#else + +#ifdef NetBSD1_3 +#if NetBSD1_3 < 2 +struct cfdriver isic_cd = { + NULL, "isic", DV_DULL +}; +#endif +#endif + +#if defined (__OpenBSD__) +struct cfdriver isic_cd = { + NULL, "isic", DV_DULL +}; +#endif + +#endif + +/* parameter and format for message producing e.g. "isic0: " */ + +#ifdef __FreeBSD__ +#define ISIC_FMT "isic%d: " +#define ISIC_PARM dev->id_unit +#define TERMFMT " " +#else +#define ISIC_FMT "%s: " +#define ISIC_PARM sc->sc_dev.dv_xname +#define TERMFMT "\n" +#endif + +extern void isic_settrace(int unit, int val); /*XXX*/ +extern int isic_gettrace(int unit); /*XXX*/ + +#ifdef __FreeBSD__ +/*---------------------------------------------------------------------------* + * isic - non-pnp device driver probe routine + *---------------------------------------------------------------------------*/ +static int +isicprobe(struct isa_device *dev) +{ + int ret = 0; + + if(dev->id_unit != next_isic_unit) + { + printf("isicprobe: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit); + return(0); + } + + switch(dev->id_flags) + { +#ifdef TEL_S0_8 + case FLAG_TELES_S0_8: + ret = isic_probe_s08(dev); + break; +#endif + +#ifdef TEL_S0_16 + case FLAG_TELES_S0_16: + ret = isic_probe_s016(dev); + break; +#endif + +#ifdef TEL_S0_16_3 + case FLAG_TELES_S0_163: + ret = isic_probe_s0163(dev); + break; +#endif + +#ifdef AVM_A1 + case FLAG_AVM_A1: + ret = isic_probe_avma1(dev); + break; +#endif + +#ifdef USR_STI + case FLAG_USR_ISDN_TA_INT: + ret = isic_probe_usrtai(dev); + break; +#endif + +#ifdef ITKIX1 + case FLAG_ITK_IX1: + ret = isic_probe_itkix1(dev); + break; +#endif + + default: + break; + } + return(ret); +} + +#else + +/*---------------------------------------------------------------------------* + * isic - device driver probe routine, dummy for NetBSD/OpenBSD + *---------------------------------------------------------------------------*/ +int +isicprobe(struct isic_attach_args *args) +{ + return 1; +} + +#endif /* __FreeBSD__ */ + +#ifdef __FreeBSD__ + +/*---------------------------------------------------------------------------* + * isic - non-pnp device driver attach routine + *---------------------------------------------------------------------------*/ +int +isicattach(struct isa_device *dev) +{ + return(isic_realattach(dev, 0)); +} + +/*---------------------------------------------------------------------------* + * isic - non-pnp and pnp device driver attach routine + *---------------------------------------------------------------------------*/ +int +isic_realattach(struct isa_device *dev, unsigned int iobase2) + +#else /* ! __FreeBSD__ */ + +int +isicattach(int flags, struct isic_softc *sc) + +#endif /* __FreeBSD__ */ +{ + int ret = 0; + char *drvid; + +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[dev->id_unit]; +#define PARM dev +#define PARM2 dev, iobase2 +#define FLAGS dev->id_flags +#else +#define PARM sc +#define PARM2 sc +#define FLAGS flags +#endif + + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + /* done in bus specific attach code for other OS */ + +#ifdef __FreeBSD__ + if(dev->id_unit != next_isic_unit) + { + printf("isicattach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit); + return(0); + } + + sc->sc_unit = dev->id_unit; +#else + isic_sc[sc->sc_unit] = sc; +#endif + + /* card dependent setup */ + switch(FLAGS) + { +#ifdef DYNALINK + case FLAG_DYNALINK: + ret = isic_attach_Dyn(PARM2); + break; +#endif + +#ifdef TEL_S0_8 + case FLAG_TELES_S0_8: + ret = isic_attach_s08(PARM); + break; +#endif + +#ifdef TEL_S0_16 + case FLAG_TELES_S0_16: + ret = isic_attach_s016(PARM); + break; +#endif + +#ifdef TEL_S0_16_3 + case FLAG_TELES_S0_163: + ret = isic_attach_s0163(PARM); + break; +#endif + +#ifdef AVM_A1 + case FLAG_AVM_A1: + ret = isic_attach_avma1(PARM); + break; +#endif + +#ifdef USR_STI + case FLAG_USR_ISDN_TA_INT: + ret = isic_attach_usrtai(PARM); + break; +#endif + +#ifdef ITKIX1 + case FLAG_ITK_IX1: + ret = isic_attach_itkix1(PARM); + break; +#endif + +/* ====================================================================== + * Only P&P cards follow below!!! + */ +#ifdef __FreeBSD__ /* we've already splitted all non-ISA stuff + out of this ISA specific part for the other + OS */ + +#ifdef AVM_PCMCIA + case FLAG_AVM_A1_PCMCIA: + ret = isic_attach_fritzpcmcia(PARM); + break; +#endif + +#ifndef __FreeBSD__ +#ifdef TEL_S0_16_3_P + case FLAG_TELES_S0_163_PnP: + ret = isic_attach_s0163P(PARM2); + break; +#endif +#endif + +#ifdef CRTX_S0_P + case FLAG_CREATIX_S0_PnP: + ret = isic_attach_Cs0P(PARM2); + break; +#endif + +#ifdef DRN_NGO + case FLAG_DRN_NGO: + ret = isic_attach_drnngo(PARM2); + break; +#endif + +#ifdef SEDLBAUER + case FLAG_SWS: + ret = isic_attach_sws(PARM); + break; +#endif + +#ifdef ELSA_QS1ISA + case FLAG_ELSA_QS1P_ISA: + ret = isic_attach_Eqs1pi(PARM2); + break; +#endif + +#endif /* __FreeBSD__ / P&P specific part */ + +/* --- XXX - don't know how to handle this - should be removed!!!! ---- */ +#ifdef amiga + case FLAG_BLMASTER: + ret = 1; /* full detection was done in caller */ + break; +#endif +/* ------------------------------------------------------------------- */ + + default: + break; + } + + if(ret == 0) + return(0); + + sc->sc_isac_version = 0; + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + break; + + default: + printf(ISIC_FMT "Error, ISAC version %d unknown!\n", + ISIC_PARM, sc->sc_isac_version); + return(0); + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + break; + + default: + printf(ISIC_FMT "Error, HSCX version %d unknown!\n", + ISIC_PARM, sc->sc_hscx_version); + return(0); + break; + }; + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + callout_handle_init(&sc->sc_T3_callout); + callout_handle_init(&sc->sc_T4_callout); +#endif + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + /* announce manufacturer and card type */ + + switch(FLAGS) + { + case FLAG_TELES_S0_8: + drvid = "Teles S0/8 or Niccy 1008"; + break; + + case FLAG_TELES_S0_16: + drvid = "Teles S0/16, Creatix ISDN S0-16 or Niccy 1016"; + break; + + case FLAG_TELES_S0_163: + drvid = "Teles S0/16.3"; + break; + + case FLAG_AVM_A1: + drvid = "AVM A1 or AVM Fritz!Card"; + break; + + case FLAG_AVM_A1_PCMCIA: + drvid = "AVM PCMCIA Fritz!Card"; + break; + + case FLAG_TELES_S0_163_PnP: + drvid = "Teles S0/PnP"; + break; + + case FLAG_CREATIX_S0_PnP: + drvid = "Creatix ISDN S0-16 P&P"; + break; + + case FLAG_USR_ISDN_TA_INT: + drvid = "USRobotics Sportster ISDN TA intern"; + break; + + case FLAG_DRN_NGO: + drvid = "Dr. Neuhaus NICCY Go@"; + break; + + case FLAG_DYNALINK: + drvid = "Dynalink IS64PH"; + break; + + case FLAG_SWS: + drvid = "Sedlbauer WinSpeed"; + break; + + case FLAG_BLMASTER: + /* board announcement was done by caller */ + drvid = (char *)0; + break; + + case FLAG_ELSA_QS1P_ISA: + drvid = "ELSA QuickStep 1000pro (ISA)"; + break; + + case FLAG_ITK_IX1: + drvid = "ITK ix1 micro"; + break; + + default: + drvid = "ERROR, unknown flag used"; + break; + } +#ifndef __FreeBSD__ + printf("\n"); +#endif + if (drvid) + printf(ISIC_FMT "%s\n", ISIC_PARM, drvid); + + /* announce chip versions */ + + if(sc->sc_isac_version >= ISAC_UNKN) + { + printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_isac_version); + sc->sc_isac_version = ISAC_UNKN; + } + else + { + printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT, + ISIC_PARM, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + } + +#ifdef __FreeBSD__ + printf("(Addr=0x%lx)\n", (u_long)ISAC_BASE); +#endif + + if(sc->sc_hscx_version >= HSCX_UNKN) + { + printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_hscx_version); + sc->sc_hscx_version = HSCX_UNKN; + } + else + { + printf(ISIC_FMT "HSCX %s" TERMFMT, + ISIC_PARM, + HSCXversion[sc->sc_hscx_version]); + } + +#ifdef __FreeBSD__ + printf("(AddrA=0x%lx, AddrB=0x%lx)\n", (u_long)HSCX_A_BASE, (u_long)HSCX_B_BASE); + + next_isic_unit++; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300003 + + /* set the interrupt handler - no need to change isa_device.h */ + dev->id_intr = (inthand2_t *)isicintr; + +#endif + +#endif /* __FreeBSD__ */ + + return(1); +#undef PARM +#undef FLAGS +} + +#endif /* NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_isic_pci.c b/sys/i4b/layer1/i4b_isic_pci.c new file mode 100644 index 0000000..3aebf08 --- /dev/null +++ b/sys/i4b/layer1/i4b_isic_pci.c @@ -0,0 +1,424 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_pci.c - PCI bus interface + * ================================== + * + * $Id: i4b_isic_pci.c,v 1.9 1998/12/05 18:04:48 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:24:36 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isic.h" + +#if defined(__FreeBSD__) +#include "opt_i4b.h" +#include "pci.h" +#endif + +#if (NISIC > 0) && (NPCI > 0) + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#if __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#include <pci/pcireg.h> +#include <pci/pcivar.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#define PCI_QS1000_ID 0x10001048 + +#define MEM0_MAPOFF 0 +#define PORT0_MAPOFF 4 +#define PORT1_MAPOFF 12 + +static char* i4b_pci_probe(pcici_t tag, pcidi_t type); +static void i4b_pci_attach(pcici_t config_id, int unit); +static int isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2); + +static u_long i4b_pci_count = 0; + +static struct pci_device i4b_pci_driver = { + "isic", + i4b_pci_probe, + i4b_pci_attach, + &i4b_pci_count, + NULL +}; + +DATA_SET (pcidevice_set, i4b_pci_driver); + +static void isic_pci_intr_sc(struct isic_softc *sc); + + +/*---------------------------------------------------------------------------* + * PCI probe routine + *---------------------------------------------------------------------------*/ +static char * +i4b_pci_probe(pcici_t tag, pcidi_t type) +{ + switch(type) + { + case PCI_QS1000_ID: + return("ELSA QuickStep 1000pro PCI ISDN adaptor"); + break; + + default: + if(bootverbose) + printf("i4b_pci_probe: unknown PCI type %ul!\n", (u_int)type); + return(NULL); + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * PCI attach routine + *---------------------------------------------------------------------------*/ +static void +i4b_pci_attach(pcici_t config_id, int unit) +{ + unsigned short iobase1; + unsigned short iobase2; + unsigned long type; + struct isic_softc *sc = &isic_sc[unit]; + + if(unit != next_isic_unit) + { + printf("i4b_pci_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", unit, next_isic_unit); + return; + } + + if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT0_MAPOFF, &iobase1))) + { + printf("i4b_pci_attach: pci_map_port 1 failed!\n"); + return; + } + + if(!(pci_map_port(config_id, PCI_MAP_REG_START+PORT1_MAPOFF, &iobase2))) + { + printf("i4b_pci_attach: pci_map_port 2 failed!\n"); + return; + } + + if(bootverbose) + printf("i4b_pci_attach: unit %d, port0 0x%x, port1 0x%x\n", unit, iobase1, iobase2); + + type = pci_conf_read(config_id, PCI_ID_REG); + + if((isic_pciattach(unit, type, iobase1, iobase2)) == 0) + return; + + if(!(pci_map_int(config_id, (void *)isic_pci_intr_sc, (void *)sc, &net_imask))) + return; +} + +/*---------------------------------------------------------------------------* + * isic - pci device driver attach routine + *---------------------------------------------------------------------------*/ +static int +isic_pciattach(int unit, u_long type, u_int iobase1, u_int iobase2) +{ + int ret = 0; + struct isic_softc *sc = &isic_sc[unit]; + + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + switch(type) + { +#ifdef ELSA_QS1PCI + case PCI_QS1000_ID: + ret = isic_attach_Eqs1pp(unit, iobase1, iobase2); + break; +#endif + default: + break; + } + + if(ret == 0) + return(ret); + + sc->sc_isac_version = 0; + sc->sc_hscx_version = 0; + + sc->sc_unit = unit; + + if(sc->sc_ipac) + { + ret = IPAC_READ(IPAC_ID); + + switch(ret) + { + case 0x01: + printf("isic%d: IPAC PSB2115 Version 1.1\n", unit); + break; + + default: + printf("isic%d: Error, IPAC version %d unknown!\n", + unit, ret); + return(0); + break; + } + } + else + { + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + printf("isic%d: ISAC %s (IOM-%c)\n", + unit, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + break; + + default: + printf("isic%d: Error, ISAC version %d unknown!\n", + unit, sc->sc_isac_version); + return(0); + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + printf("isic%d: HSCX %s\n", + unit, + HSCXversion[sc->sc_hscx_version]); + break; + + default: + printf("isic%d: Error, HSCX version %d unknown!\n", + unit, sc->sc_hscx_version); + return(0); + break; + } + } + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + callout_handle_init(&sc->sc_T3_callout); + callout_handle_init(&sc->sc_T4_callout); +#endif + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + next_isic_unit++; + + return(1); +} + +/*---------------------------------------------------------------------------* + * isic - PCI device driver interrupt routine + *---------------------------------------------------------------------------*/ +static void +isic_pci_intr_sc(struct isic_softc *sc) +{ + if(sc->sc_ipac == 0) /* HSCX/ISAC interupt routine */ + { + register u_char hscx_irq_stat; + register u_char isac_irq_stat; + + for(;;) + { + /* get hscx irq status from hscx b ista */ + hscx_irq_stat = + HSCX_READ(HSCX_CH_B, H_ISTA) & ~HSCX_B_IMASK; + + /* get isac irq status */ + isac_irq_stat = ISAC_READ(I_ISTA); + + /* do as long as there are pending irqs in the chips */ + if(!hscx_irq_stat && !isac_irq_stat) + break; + + if(hscx_irq_stat & (HSCX_ISTA_RME | HSCX_ISTA_RPF | + HSCX_ISTA_RSC | HSCX_ISTA_XPR | + HSCX_ISTA_TIN | HSCX_ISTA_EXB)) + { + isic_hscx_irq(sc, hscx_irq_stat, + HSCX_CH_B, + hscx_irq_stat & HSCX_ISTA_EXB); + } + + if(hscx_irq_stat & (HSCX_ISTA_ICA | HSCX_ISTA_EXA)) + { + isic_hscx_irq(sc, + HSCX_READ(HSCX_CH_A, H_ISTA) & ~HSCX_A_IMASK, + HSCX_CH_A, + hscx_irq_stat & HSCX_ISTA_EXA); + } + + if(isac_irq_stat) + { /* isac handler */ + isic_isac_irq(sc, isac_irq_stat); + } + } + + HSCX_WRITE(0, H_MASK, 0xff); + ISAC_WRITE(I_MASK, 0xff); + HSCX_WRITE(1, H_MASK, 0xff); + + DELAY(100); + + HSCX_WRITE(0, H_MASK, HSCX_A_IMASK); + ISAC_WRITE(I_MASK, ISAC_IMASK); + HSCX_WRITE(1, H_MASK, HSCX_B_IMASK); + } + else /* IPAC interrupt routine */ + { + register u_char ipac_irq_stat; + + for(;;) + { + /* get global irq status */ + + ipac_irq_stat = (IPAC_READ(IPAC_ISTA)) & 0x3f; + + /* do as long as there are pending irqs in the chip */ + if(!ipac_irq_stat) + break; + + /* check hscx a */ + + if(ipac_irq_stat & (IPAC_ISTA_ICA | IPAC_ISTA_EXA)) + { + /* HSCX A interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_A, H_ISTA), + HSCX_CH_A, + ipac_irq_stat & IPAC_ISTA_EXA); + } + if(ipac_irq_stat & (IPAC_ISTA_ICB | IPAC_ISTA_EXB)) + { + /* HSCX B interrupt */ + isic_hscx_irq(sc, HSCX_READ(HSCX_CH_B, H_ISTA), + HSCX_CH_B, + ipac_irq_stat & IPAC_ISTA_EXB); + } + if(ipac_irq_stat & (IPAC_ISTA_ICD | IPAC_ISTA_EXD)) + { + /* ISAC interrupt */ + isic_isac_irq(sc, ISAC_READ(I_ISTA)); + } + } + + IPAC_WRITE(IPAC_MASK, 0xff); + DELAY(50); + IPAC_WRITE(IPAC_MASK, 0xc0); + } +} + +#endif /* (NISIC > 0) && (NPCI > 0) */ + diff --git a/sys/i4b/layer1/i4b_isic_pcmcia.c b/sys/i4b/layer1/i4b_isic_pcmcia.c new file mode 100644 index 0000000..a1fb22a --- /dev/null +++ b/sys/i4b/layer1/i4b_isic_pcmcia.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 1998 Matthias Apitz. All rights reserved. + * + * Copyright (c) 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_pcmcia.c - i4b FreeBSD PCMCIA support + * ---------------------------------------------- + * + * $Id: i4b_isic_pcmcia.c,v 1.3 1998/12/16 09:32:50 hm Exp $ + * + * last edit-date: [Mon Dec 14 17:30:09 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +#include "isic.h" +#include "opt_i4b.h" +#include "card.h" + +#if (NISIC > 0) && (NCARD > 0) + +#include "apm.h" +#include <sys/param.h> +#include <sys/select.h> +#include <i386/isa/isa_device.h> + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> +#include <machine/clock.h> +#include <i386/isa/isa_device.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include <pccard/cardinfo.h> +#include <pccard/slot.h> +#include <pccard/driver.h> + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +/* + * PC-Card (PCMCIA) specific code. + */ +static int isic_pccard_init __P((struct pccard_devinfo *)); +static void isic_unload __P((struct pccard_devinfo *)); +static int isic_card_intr __P((struct pccard_devinfo *)); + +static struct pccard_device isic_info = { + "isic", + isic_pccard_init, + isic_unload, + isic_card_intr, + 0, /* Attributes - presently unused */ + &net_imask +}; + +DATA_SET(pccarddrv_set, isic_info); + +/* + * Initialize the device - called from Slot manager. + */ + +static int opened = 0; /* our cards status */ + +static int isic_pccard_init(devi) +struct pccard_devinfo *devi; +{ + struct isa_device *is = &devi->isahd; + struct isic_softc *sc = &isic_sc[is->id_unit]; + + if ((1 << is->id_unit) & opened) + return(EBUSY); + + opened |= 1 << is->id_unit; + printf("isic%d: PCMCIA init, irqmask = 0x%x (%d), iobase = 0x%x\n", + is->id_unit, is->id_irq, devi->slt->irq, is->id_iobase); + +#if 0 + /* XXX: problems resolving isic_probe_avma1_pcmcia() /phk */ + /* + * look if there is really an AVM PCMCIA Fritz!Card and + * setup the card specific stuff + */ + isic_probe_avma1_pcmcia(is); +#endif + + /* ap: + * XXX what's to do with the return value? + */ + + /* + * try to attach the PCMCIA card as a normal A1 card + */ + isicattach(is); + return(0); +} + +static void isic_unload(devi) +struct pccard_devinfo *devi; +{ + struct isa_device *is = &devi->isahd; + printf("isic%d: unloaded\n", is->id_unit); + opened &= ~(1 << is->id_unit); +} + +/* + * card_intr - Shared interrupt called from + * front end of PC-Card handler. + */ +static int isic_card_intr(devi) +struct pccard_devinfo *devi; +{ + isicintr(devi->isahd.id_unit); + return(1); +} + +#endif /* (NISIC > 0) && (NCARD > 0) */ +#endif /* __FreeBSD__ */ diff --git a/sys/i4b/layer1/i4b_isic_pnp.c b/sys/i4b/layer1/i4b_isic_pnp.c new file mode 100644 index 0000000..ed1892d9 --- /dev/null +++ b/sys/i4b/layer1/i4b_isic_pnp.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 1998 Eivind Eklund. All rights reserved. + * + * Copyright (c) 1998 German Tischler. All rights reserved. + * + * Copyright (c) 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_isic_pnp.c - i4b pnp support + * -------------------------------- + * + * $Id: i4b_isic_pnp.c,v 1.15 1998/12/20 11:07:59 hm Exp $ + * + * last edit-date: [Fri Dec 18 20:54:56 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +#include "pnp.h" +#include "isic.h" +#include "opt_i4b.h" + +#if (NISIC > 0) && (NPNP > 0) + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <net/if.h> + +#if defined(__FreeBSD__) && __FreeBSD__ < 3 +#include "ioconf.h" +extern void isicintr(int unit); /* XXX this gives a compiler warning */ + /* on one 2.2.7 machine but no */ + /* warning on another one !? (-hm) */ +#endif + +#if (defined(__FreeBSD_version) && __FreeBSD_version >= 300006) +extern void isicintr(int unit); +#endif + +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/pnp.h> + +#include <i4b/include/i4b_global.h> +#include <machine/i4b_ioctl.h> +#include <i4b/layer1/i4b_l1.h> + +#define VID_TEL163PNP 0x10212750 /* Teles 16.3 PnP */ +#define VID_CREATIXPP 0x0000980e /* Creatix S0/16 P+P */ +#define VID_DYNALINK 0x88167506 /* Dynalink */ +#define VID_SEDLBAUER 0x0100274c /* Sedlbauer WinSpeed */ +#define VID_NICCYGO 0x5001814c /* Neuhaus Niccy GO@ */ +#define VID_ELSAQS1P 0x33019315 /* ELSA Quickstep1000pro*/ + +static struct i4b_pnp_ids { + u_long vend_id; + char *id_str; +} i4b_pnp_ids[] = { + { VID_TEL163PNP, "Teles 16.3 PnP" }, + { VID_CREATIXPP, "Creatix S0/16 P+P" }, + { VID_DYNALINK, "Dynalink IS64PH" }, + { VID_SEDLBAUER, "Sedlbauer WinSpeed" }, + { VID_NICCYGO, "Dr.Neuhaus Niccy Go@" }, + { VID_ELSAQS1P, "ELSA QuickStep 1000pro"}, + { 0 } +}; + +extern struct isa_driver isicdriver; + +static int isic_pnpprobe(struct isa_device *dev, unsigned int iobase2); +static char *i4b_pnp_probe(u_long csn, u_long vend_id); +static void i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev); + +static u_long ni4b_pnp = 0; + +static struct pnp_device i4b_pnp = { + "i4b_pnp", + i4b_pnp_probe, + i4b_pnp_attach, + &ni4b_pnp, + &net_imask +}; + +DATA_SET(pnpdevice_set, i4b_pnp); + +/*---------------------------------------------------------------------------* + * PnP probe routine + *---------------------------------------------------------------------------*/ +static char * +i4b_pnp_probe(u_long csn, u_long vend_id) +{ + struct i4b_pnp_ids *ids; + char *string = NULL; + + /* search table of knowd id's */ + + for(ids = i4b_pnp_ids; ids->vend_id != 0; ids++) + { + if(vend_id == ids->vend_id) + { + string = ids->id_str; + break; + } + } + + if(string) + { + struct pnp_cinfo spci; + + read_pnp_parms(&spci, 0); + + if((spci.enable == 0) || (spci.flags & 0x01)) + { + printf("CSN %d (%s) is disabled.\n", (int)csn, string); + return (NULL); + } + } + return(string); +} + +/*---------------------------------------------------------------------------* + * PnP attach routine + *---------------------------------------------------------------------------*/ +static void +i4b_pnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) +{ + struct pnp_cinfo spci; + struct isa_device *isa_devp; + + if(dev->id_unit != next_isic_unit) + { + printf("i4b_pnp_attach: Error: new unit (%d) != next_isic_unit (%d)!\n", dev->id_unit, next_isic_unit); + return; + } + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for %s\n", + dev->id_unit, dev->id_unit, name); + return; + } + + if(read_pnp_parms(&spci, 0) == 0) + { + printf("isic%d: read_pnp_parms error for %s\n", + dev->id_unit, name); + return; + } + + if(bootverbose) + { + printf("isic%d: vendorid = 0x%08x port0 = 0x%04x, port1 = 0x%04x, irq = %d\n", + dev->id_unit, spci.vendor_id, spci.port[0], spci.port[1], spci.irq[0]); + } + + dev->id_iobase = spci.port[0]; + dev->id_irq = (1 << spci.irq[0]); + dev->id_intr = (inthand2_t *) isicintr; + dev->id_drq = -1; + +/* XXX add dev->id_alive init here ! ?? */ + + switch(spci.vendor_id) + { + case VID_TEL163PNP: + dev->id_flags = FLAG_TELES_S0_163_PnP; + break; + case VID_CREATIXPP: + dev->id_flags = FLAG_CREATIX_S0_PnP; + break; + case VID_DYNALINK: + dev->id_flags = FLAG_DYNALINK; + break; + case VID_SEDLBAUER: + dev->id_flags = FLAG_SWS; + break; + case VID_NICCYGO: + dev->id_flags = FLAG_DRN_NGO; + break; + case VID_ELSAQS1P: + dev->id_flags = FLAG_ELSA_QS1P_ISA; + break; + } + + write_pnp_parms(&spci, 0); + enable_pnp_card(); + + if(dev->id_driver == NULL) + { + dev->id_driver = &isicdriver; + + isa_devp = find_isadev(isa_devtab_net, &isicdriver, 0); + + if(isa_devp != NULL) + { + dev->id_id = isa_devp->id_id; + } + } + + if((dev->id_alive = isic_pnpprobe(dev, spci.port[1])) != 0) + { +/* XXX dev->id_alive is the size of the port area used ! */ + isic_realattach(dev, spci.port[1]); + } + else + { + printf("isic%d: probe failed!\n", dev->id_unit); + } +} + +/*---------------------------------------------------------------------------* + * isic - pnp device driver probe routine + *---------------------------------------------------------------------------*/ +static int +isic_pnpprobe(struct isa_device *dev, unsigned int iobase2) +{ + int ret = 0; + + switch(dev->id_flags) + { +#ifndef __FreeBSD__ +#ifdef TEL_S0_16_3_P + case FLAG_TELES_S0_163_PnP: + ret = isic_probe_s0163P(dev, iobase2); + break; +#endif +#endif + +#ifdef CRTX_S0_P + case FLAG_CREATIX_S0_PnP: + ret = isic_probe_Cs0P(dev, iobase2); + break; +#endif + +#ifdef DRN_NGO + case FLAG_DRN_NGO: + ret = isic_probe_drnngo(dev, iobase2); + break; +#endif + +#ifdef SEDLBAUER + case FLAG_SWS: + ret = 8; /* pnp only, nothing to probe */ + break; +#endif + +#ifdef DYNALINK + case FLAG_DYNALINK: + ret = isic_probe_Dyn(dev, iobase2); + break; +#endif + +#ifdef ELSA_QS1ISA + case FLAG_ELSA_QS1P_ISA: + ret = isic_probe_Eqs1pi(dev, iobase2); + break; +#endif + default: + break; + } + return(ret); +} + +#endif /* (NISIC > 0) && (NPNP > 0) */ +#endif /* __FreeBSD__ */ diff --git a/sys/i4b/layer1/i4b_itk_ix1.c b/sys/i4b/layer1/i4b_itk_ix1.c new file mode 100644 index 0000000..f7491cd --- /dev/null +++ b/sys/i4b/layer1/i4b_itk_ix1.c @@ -0,0 +1,430 @@ +/* + * Copyright (c) 1998 Martin Husemann <martin@rumolt.teuto.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_itk_ix1.c - ITK ix1 micro passive card driver for isdn4bsd + * -------------------------------------------------------------- + * + * $Id: i4b_itk_ix1.c,v 1.1 1998/12/16 13:43:20 hm Exp $ + * + * last edit-date: [Wed Dec 16 14:46:36 1998] + * + *--------------------------------------------------------------------------- + * + * The ITK ix1 micro ISDN card is an ISA card with one region + * of four io ports mapped and a fixed irq all jumpered on the card. + * Access to the board is straight forward and simmilar to + * the ELSA and DYNALINK cards. If a PCI version of this card + * exists all we need is probably a pci-bus attachment, all + * this low level routines should work imediately. + * + * To reset the card: + * - write 0x01 to ITK_CONFIG + * - wait >= 10 ms + * - write 0x00 to ITK_CONFIG + * + * To read or write data: + * - write address to ITK_ALE port + * - read data from or write data to ITK_ISAC_DATA port or ITK_HSCX_DATA port + * The two HSCX channel registers are offset by HSCXA (0x00) and HSCXB (0x40). + * + * XXX - A reasonable probe routine has to be written. + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(ITKIX1) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> + +#define ITK_ISAC_DATA 0 +#define ITK_HSCX_DATA 1 +#define ITK_ALE 2 +#define ITK_CONFIG 3 +#define ITK_IO_SIZE 4 + +#define HSCXA 0 +#define HSCXB 0x40 + +#ifndef __FreeBSD__ +static void itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size); +static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size); +static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data); +static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs); +#else +static u_char itkix1_read_reg(u_char *base, u_int offset); +static void itkix1_write_reg(u_char *base, u_int offset, u_int v); +static void itkix1_read_fifo(void *base, const void *buf, size_t len); +static void itkix1_write_fifo(void *base, const void *buf, size_t len); +#endif + +/* + * Probe for card + */ +#ifdef __FreeBSD__ +int +isic_probe_itkix1(struct isa_device *dev) +{ + u_int8_t hd, cd; + int ret; + + hd = inb(dev->id_iobase + ITK_HSCX_DATA); + cd = inb(dev->id_iobase + ITK_CONFIG); + + ret = (hd == 0 && cd == 0xfc); + +#define ITK_PROBE_DEBUG +#ifdef ITK_PROBE_DEBUG + printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n", + hd, cd, ret ? "succeeded" : "failed"); + return 1; +#else + return ret; +#endif +} +#else +int +isic_probe_itkix1(struct isic_attach_args *ia) +{ + bus_space_tag_t t = ia->ia_maps[0].t; + bus_space_handle_t h = ia->ia_maps[0].h; + u_int8_t hd, cd; + int ret; + + hd = bus_space_read_1(t, h, ITK_HSCX_DATA); + cd = bus_space_read_1(t, h, ITK_CONFIG); + + ret = (hd == 0 && cd == 0xfc); + +#define ITK_PROBE_DEBUG +#ifdef ITK_PROBE_DEBUG + printf("\nITK ix1 micro probe: hscx = 0x%02x, config = 0x%02x, would have %s\n", + hd, cd, ret ? "succeeded" : "failed"); + return 1; +#else + return ret; +#endif +} +#endif + +/* + * Attach card + */ +#ifdef __FreeBSD__ +int +isic_attach_itkix1(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + sc->sc_irq = dev->id_irq; + + dev->id_msize = 0; + + /* check if we got an iobase */ + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = itkix1_read_reg; + sc->writereg = itkix1_write_reg; + sc->readfifo = itkix1_read_fifo; + sc->writefifo = itkix1_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_ITKIX1; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + ISAC_BASE = (caddr_t) sc->sc_port; + HSCX_A_BASE = (caddr_t) sc->sc_port + 1; + HSCX_B_BASE = (caddr_t) sc->sc_port + 2; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for ITK ix1 micro\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + outb((dev->id_iobase)+ITK_CONFIG, 1); + DELAY(SEC_DELAY / 10); + outb((dev->id_iobase)+ITK_CONFIG, 0); + DELAY(SEC_DELAY / 10); + return(1); +} + +#else + +int isic_attach_itkix1(struct isic_softc *sc) +{ + /* setup access routines */ + sc->clearirq = NULL; + sc->readreg = itkix1_read_reg; + sc->writereg = itkix1_write_reg; + sc->readfifo = itkix1_read_fifo; + sc->writefifo = itkix1_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_ITKIX1; + + /* setup IOM bus type */ + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* Read HSCX A/B VSTR. Expected value is 0x05 (V2.1). */ + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("%s: HSCX VSTR test failed for ITK ix1 micro\n", + sc->sc_dev.dv_xname); + printf("%s: HSC0: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR)); + printf("%s: HSC1: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR)); + return 0; + } + + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 1); + DELAY(SEC_DELAY / 10); + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, ITK_CONFIG, 0); + DELAY(SEC_DELAY / 10); + return 1; +} + +#endif + +#ifdef __FreeBSD__ +static void +itkix1_read_fifo(void *buf, const void *base, size_t len) +{ + int port = (u_long)base & ~0x0003; + switch ((u_long)base & 3) { + case 0: /* ISAC */ + outb(port+ITK_ALE, 0); + insb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len); + break; + case 1: /* HSCXA */ + outb(port+ITK_ALE, HSCXA); + insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len); + break; + case 2: /* HSCXB */ + outb(port+ITK_ALE, HSCXB); + insb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len); + break; + } +} +#else +static void +itkix1_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, 0); + bus_space_read_multi_1(t, h, ITK_ISAC_DATA, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA); + bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB); + bus_space_read_multi_1(t, h, ITK_HSCX_DATA, buf, size); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static void +itkix1_write_fifo(void *base, const void *buf, size_t len) +{ + int port = (u_long)base & ~0x0003; + switch ((u_long)base & 3) { + case 0: /* ISAC */ + outb(port+ITK_ALE, 0); + outsb(port+ITK_ISAC_DATA, (u_char *)buf, (u_int)len); + break; + case 1: /* HSCXA */ + outb(port+ITK_ALE, HSCXA); + outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len); + break; + case 2: /* HSCXB */ + outb(port+ITK_ALE, HSCXB); + outsb(port+ITK_HSCX_DATA, (u_char *)buf, (u_int)len); + break; + } +} +#else +static void itkix1_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, 0); + bus_space_write_multi_1(t, h, ITK_ISAC_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA); + bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB); + bus_space_write_multi_1(t, h, ITK_HSCX_DATA, (u_int8_t*)buf, size); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static void +itkix1_write_reg(u_char *base, u_int offset, u_int v) +{ + int port = (u_long)base & ~0x0003; + switch ((u_long)base & 3) { + case 0: /* ISAC */ + outb(port+ITK_ALE, offset); + outb(port+ITK_ISAC_DATA, (u_char)v); + break; + case 1: /* HSCXA */ + outb(port+ITK_ALE, HSCXA+offset); + outb(port+ITK_HSCX_DATA, (u_char)v); + break; + case 2: /* HSCXB */ + outb(port+ITK_ALE, HSCXB+offset); + outb(port+ITK_HSCX_DATA, (u_char)v); + break; + } +} +#else +static void itkix1_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, offs); + bus_space_write_1(t, h, ITK_ISAC_DATA, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA+offs); + bus_space_write_1(t, h, ITK_HSCX_DATA, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB+offs); + bus_space_write_1(t, h, ITK_HSCX_DATA, data); + break; + } +} +#endif + +#ifdef __FreeBSD__ +static u_char +itkix1_read_reg(u_char *base, u_int offset) +{ + int port = (u_long)base & ~0x0003; + switch ((u_long)base & 3) { + case 0: /* ISAC */ + outb(port+ITK_ALE, offset); + return (inb(port+ITK_ISAC_DATA)); + case 1: /* HSCXA */ + outb(port+ITK_ALE, HSCXA+offset); + return (inb(port+ITK_HSCX_DATA)); + case 2: /* HSCXB */ + outb(port+ITK_ALE, HSCXB+offset); + return (inb(port+ITK_HSCX_DATA)); + } +} +#else +static u_int8_t itkix1_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, ITK_ALE, offs); + return bus_space_read_1(t, h, ITK_ISAC_DATA); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, ITK_ALE, HSCXA+offs); + return bus_space_read_1(t, h, ITK_HSCX_DATA); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, ITK_ALE, HSCXB+offs); + return bus_space_read_1(t, h, ITK_HSCX_DATA); + } + return 0; +} +#endif + +#endif /* ITKIX1 */ diff --git a/sys/i4b/layer1/i4b_l1.c b/sys/i4b/layer1/i4b_l1.c new file mode 100644 index 0000000..96497c5 --- /dev/null +++ b/sys/i4b/layer1/i4b_l1.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1.c - isdn4bsd layer 1 handler + * ----------------------------------- + * + * $Id: i4b_l1.c,v 1.27 1998/12/05 18:04:51 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:24:52 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "isic.h" +#else +#define NISIC 1 /* don't bother */ +#endif +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <machine/stdarg.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +unsigned int i4b_l1_debug = L1_DEBUG_DEFAULT; + +static int ph_data_req(int, struct mbuf *, int); +static int ph_activate_req(int); + +/* from i4btrc driver i4b_trace.c */ +extern int get_trace_data_from_l1(int unit, int what, int len, char *buf); + +/* from layer 2 */ +extern int i4b_ph_data_ind(int unit, struct mbuf *m); +extern int i4b_ph_activate_ind(int unit); +extern int i4b_ph_deactivate_ind(int unit); +extern int i4b_mph_attach_ind(int unit); +extern int i4b_mph_status_ind(int, int, int); + +/* layer 1 lme */ +static int i4b_mph_command_req(int, int, int); + +/* jump table */ +struct i4b_l1l2_func i4b_l1l2_func = { + + /* Layer 1 --> Layer 2 */ + + (int (*)(int, struct mbuf *)) i4b_ph_data_ind, + (int (*)(int)) i4b_ph_activate_ind, + (int (*)(int)) i4b_ph_deactivate_ind, + + /* Layer 2 --> Layer 1 */ + + (int (*)(int, struct mbuf *, int)) ph_data_req, + (int (*)(int)) ph_activate_req, + + /* Layer 1 --> upstream, ISDN trace data */ + + (int (*)(i4b_trace_hdr_t *, int, u_char *)) get_trace_data_from_l1, + + /* Driver control and status information */ + + (int (*)(int, int, int)) i4b_mph_status_ind, + (int (*)(int, int, int)) i4b_mph_command_req, +}; + +/*---------------------------------------------------------------------------* + * + * L2 -> L1: PH-DATA-REQUEST + * ========================= + * + * parms: + * unit physical interface unit number + * m mbuf containing L2 frame to be sent out + * freeflag MBUF_FREE: free mbuf here after having sent + * it out + * MBUF_DONTFREE: mbuf is freed by Layer 2 + * returns: + * ==0 fail, nothing sent out + * !=0 ok, frame sent out + * + *---------------------------------------------------------------------------*/ +static int +ph_data_req(int unit, struct mbuf *m, int freeflag) +{ + u_char cmd; + int s; + +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + +#ifdef NOTDEF + DBGL1(L1_PRIM, "PH-DATA-REQ", ("unit %d, freeflag=%d\n", unit, freeflag)); +#endif + + if(m == NULL) /* failsafe */ + return (0); + + s = SPLI4B(); + + if(sc->sc_I430state == ST_F3) /* layer 1 not running ? */ + { + DBGL1(L1_I_ERR, "ph_data_req", ("still in state F3!\n")); + ph_activate_req(unit); + } + + if(sc->sc_state & ISAC_TX_ACTIVE) + { + if(sc->sc_obuf2 == NULL) + { + sc->sc_obuf2 = m; /* save mbuf ptr */ + + if(freeflag) + sc->sc_freeflag2 = 1; /* IRQ must mfree */ + else + sc->sc_freeflag2 = 0; /* IRQ must not mfree */ + + DBGL1(L1_I_MSG, "ph_data_req", ("using 2nd ISAC TX buffer, state = %s\n", isic_printstate(sc))); + + if(sc->sc_trace & TRACE_D_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = unit; + hdr.type = TRC_CH_D; + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, m->m_len, m->m_data); + } + splx(s); + return(1); + } + + DBGL1(L1_I_ERR, "ph_data_req", ("No Space in TX FIFO, state = %s\n", isic_printstate(sc))); + + if(freeflag == MBUF_FREE) + i4b_Dfreembuf(m); + + splx(s); + return (0); + } + + if(sc->sc_trace & TRACE_D_TX) + { + i4b_trace_hdr_t hdr; + hdr.unit = unit; + hdr.type = TRC_CH_D; + hdr.dir = FROM_TE; + hdr.count = ++sc->sc_trace_dcount; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, m->m_len, m->m_data); + } + + sc->sc_state |= ISAC_TX_ACTIVE; /* set transmitter busy flag */ + + DBGL1(L1_I_MSG, "ph_data_req", ("ISAC_TX_ACTIVE set\n")); + + sc->sc_freeflag = 0; /* IRQ must NOT mfree */ + + ISAC_WRFIFO(m->m_data, min(m->m_len, ISAC_FIFO_LEN)); /* output to TX fifo */ + + if(m->m_len > ISAC_FIFO_LEN) /* message > 32 bytes ? */ + { + sc->sc_obuf = m; /* save mbuf ptr */ + sc->sc_op = m->m_data + ISAC_FIFO_LEN; /* ptr for irq hdl */ + sc->sc_ol = m->m_len - ISAC_FIFO_LEN; /* length for irq hdl */ + + if(freeflag) + sc->sc_freeflag = 1; /* IRQ must mfree */ + + cmd = ISAC_CMDR_XTF; + } + else + { + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + + if(freeflag) + i4b_Dfreembuf(m); + + cmd = ISAC_CMDR_XTF | ISAC_CMDR_XME; + } + + ISAC_WRITE(I_CMDR, cmd); + ISACCMDRWRDELAY(); + + splx(s); + + return(1); +} + +/*---------------------------------------------------------------------------* + * + * L2 -> L1: PH-ACTIVATE-REQUEST + * ============================= + * + * parms: + * unit physical interface unit number + * + * returns: + * ==0 + * !=0 + * + *---------------------------------------------------------------------------*/ +static int +ph_activate_req(int unit) +{ + +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + + DBGL1(L1_PRIM, "PH-ACTIVATE-REQ", ("unit %d\n", unit)); + isic_next_state(sc, EV_PHAR); + return(0); +} + +/*---------------------------------------------------------------------------* + * command from the upper layers + *---------------------------------------------------------------------------*/ +static int +i4b_mph_command_req(int unit, int command, int parm) +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[unit]; +#else + struct isic_softc *sc = isic_find_sc(unit); +#endif + + switch(command) + { + case CMR_DOPEN: /* daemon running */ + DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DOPEN\n", unit)); + sc->sc_enabled = 1; + break; + + case CMR_DCLOSE: /* daemon not running */ + DBGL1(L1_PRIM, "MPH-COMMAND-REQ", ("unit %d, command = CMR_DCLOSE\n", unit)); + sc->sc_enabled = 0; + break; + + default: + DBGL1(L1_ERROR, "i4b_mph_command_req", ("ERROR, unknown command = %d, unit = %d, parm = %d\n", command, unit, parm)); + break; + } + + return(0); +} + +#endif /* NISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_l1.h b/sys/i4b/layer1/i4b_l1.h new file mode 100644 index 0000000..2b15ccc --- /dev/null +++ b/sys/i4b/layer1/i4b_l1.h @@ -0,0 +1,438 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *---------------------------------------------------------------------------* + * + * i4b_l1.h - isdn4bsd layer 1 header file + * --------------------------------------- + * + * $Id: i4b_l1.h,v 1.54 1998/12/17 04:55:39 hm Exp $ + * + * last edit-date: [Mon Dec 14 10:41:36 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef I4B_L1_H_ +#define I4B_L1_H_ + +#include <i4b/include/i4b_l3l4.h> + +/*--------------------------------------------------------------------------- + * kernel config file flags definition + *---------------------------------------------------------------------------*/ + /* XXX: we do need these only for real ISA (not even ISAPNP cards), and only + * because we are not confident enough in the general ISA probe routine (as + * practiced by the NetBSD variant). *And* it is completely redundant to the + * various options enabling only a few card's support routines to be compiled + * in. Probably the current truth is: this is usefull for anybody with more + * than one supported real ISA card. It is not usefull in generic configs, + * nor in typical one-controller-only configurations. + * Further - it is identical to the CARD_TYPEP_xxx definitions in + * ../machine/i4b_ioctl.h. + */ +#define FLAG_TELES_S0_8 1 +#define FLAG_TELES_S0_16 2 +#define FLAG_TELES_S0_163 3 +#define FLAG_AVM_A1 4 +#define FLAG_TELES_S0_163_PnP 5 /* XXX - not needed, remove! */ +#define FLAG_CREATIX_S0_PnP 6 /* XXX - not needed, remove! */ +#define FLAG_USR_ISDN_TA_INT 7 +#define FLAG_DRN_NGO 8 /* XXX - not needed, remove! */ +#define FLAG_SWS 9 /* XXX - not needed, remove! */ +#define FLAG_AVM_A1_PCMCIA 10 /* XXX - not needed, remove! */ +#define FLAG_DYNALINK 11 /* XXX - not needed, remove! */ +#define FLAG_BLMASTER 12 +#define FLAG_ELSA_QS1P_ISA 13 /* XXX - not needed, remove! */ +#define FLAG_ELSA_QS1P_PCI 14 /* XXX - not needed, remove! */ +#define FLAG_SIEMENS_ITALK 15 +#define FLAG_ELSA_MLIMC 16 /* XXX - not needed, remove! */ +#define FLAG_ELSA_MLMCALL 17 /* XXX - not needed, remove! */ +#define FLAG_ITK_IX1 18 + +#define SEC_DELAY 1000000 /* one second DELAY for DELAY*/ + +#define MAX_DFRAME_LEN 264 /* max length of a D frame */ + +#define min(a,b) ((a)<(b)?(a):(b)) + +#ifndef __FreeBSD__ +/* We try to map as few as possible as small as possible io and/or + memory regions. Each card defines its own interpretation of this + mapping array. At probe time we have a fixed size array, later + (when the card type is known) we allocate a minimal array + dynamically. */ + +#define ISIC_MAX_IO_MAPS 49 /* no cardtype needs more yet */ + +/* one entry in mapping array */ +struct isic_io_map { + bus_space_tag_t t; /* which bus-space is this? */ + bus_space_handle_t h; /* handle of mapped bus space region */ + bus_size_t offset; /* offset into region */ + bus_size_t size; /* size of region, zero if not ours + (i.e.: don't ever unmap it!) */ +}; + +/* this is passed around at probe time (no struct isic_softc yet) */ +struct isic_attach_args { + int ia_flags; /* flags from config file */ + int ia_num_mappings; /* number of io mappings provided */ + struct isic_io_map ia_maps[ISIC_MAX_IO_MAPS]; +}; +#endif + +#ifdef __FreeBSD__ +extern int next_isic_unit; +#endif + +/*---------------------------------------------------------------------------* + * isic_Bchan: the state of one B channel + *---------------------------------------------------------------------------*/ +typedef struct +{ + int unit; /* cards unit number */ + int channel; /* which channel is this*/ + +#ifdef __FreeBSD__ + caddr_t hscx; /* HSCX address */ +#endif + + u_char hscx_mask; /* HSCX interrupt mask */ + + int bprot; /* B channel protocol */ + + int state; /* this channels state */ +#define HSCX_IDLE 0x00 /* channel idle */ +#define HSCX_TX_ACTIVE 0x01 /* tx running */ + + /* receive data from ISDN */ + + struct ifqueue rx_queue; /* receiver queue */ + + int rxcount; /* rx statistics counter*/ + + struct mbuf *in_mbuf; /* rx input buffer */ + u_char *in_cbptr; /* curr buffer pointer */ + int in_len; /* rx input buffer len */ + + /* transmit data to ISDN */ + + struct ifqueue tx_queue; /* transmitter queue */ + + int txcount; /* tx statistics counter*/ + + struct mbuf *out_mbuf_head; /* first mbuf in possible chain */ + struct mbuf *out_mbuf_cur; /* current mbuf in possbl chain */ + unsigned char *out_mbuf_cur_ptr; /* data pointer into mbuf */ + int out_mbuf_cur_len; /* remaining bytes in mbuf */ + + /* link between b channel and driver */ + + isdn_link_t isdn_linktab; /* b channel addresses */ + drvr_link_t *drvr_linktab; /* ptr to driver linktab*/ + + /* statistics */ + + /* RSTA */ + + int stat_VFR; /* HSCX RSTA Valid FRame */ + int stat_RDO; /* HSCX RSTA Rx Data Overflow */ + int stat_CRC; /* HSCX RSTA CRC */ + int stat_RAB; /* HSCX RSTA Rx message ABorted */ + + /* EXIR */ + + int stat_XDU; /* HSCX EXIR tx data underrun */ + int stat_RFO; /* HSCX EXIR rx frame overflow */ + +} isic_Bchan_t; + +/*---------------------------------------------------------------------------* + * isic_softc: the state of the layer 1 of the D channel + *---------------------------------------------------------------------------*/ +struct isic_softc +{ +#ifndef __FreeBSD__ + /* We are inherited from this class. All drivers must have this + as their first entry in struct softc. */ + struct device sc_dev; +#endif + + int sc_unit; /* unit number */ + int sc_irq; /* interrupt vector */ + +#ifdef __FreeBSD__ + int sc_port; /* port base address */ +#else + u_int sc_maddr; /* "memory address" for card config register */ + int sc_num_mappings; /* number of io mappings provided */ + struct isic_io_map *sc_maps; +#define MALLOC_MAPS(sc) \ + (sc)->sc_maps = (struct isic_io_map*)malloc(sizeof((sc)->sc_maps[0])*(sc)->sc_num_mappings, M_DEVBUF, 0) +#endif + + int sc_cardtyp; /* CARD_TYPEP_xxxx */ + + int sc_bustyp; /* IOM1 or IOM2 */ +#define BUS_TYPE_IOM1 0x01 +#define BUS_TYPE_IOM2 0x02 + + int sc_trace; /* output protocol data for tracing */ + unsigned int sc_trace_dcount;/* d channel trace frame counter */ + unsigned int sc_trace_bcount;/* b channel trace frame counter */ + + int sc_state; /* ISAC state flag */ +#define ISAC_IDLE 0x00 /* state = idle */ +#define ISAC_TX_ACTIVE 0x01 /* state = transmitter active */ + + int sc_init_tries; /* no of out tries to access S0 */ + +#ifdef __FreeBSD__ + caddr_t sc_vmem_addr; /* card RAM virtual memory base */ + caddr_t sc_isac; /* ISAC port base addr */ +#define ISAC_BASE (sc->sc_isac) + + caddr_t sc_ipacbase; /* IPAC port base addr */ +#define IPAC_BASE (sc->sc_ipacbase) +#endif + + u_char sc_isac_mask; /* ISAC IRQ mask */ +#define ISAC_IMASK (sc->sc_isac_mask) + + isic_Bchan_t sc_chan[2]; /* B-channel state */ +#define HSCX_A_BASE (sc->sc_chan[0].hscx) +#define HSCX_A_IMASK (sc->sc_chan[0].hscx_mask) +#define HSCX_B_BASE (sc->sc_chan[1].hscx) +#define HSCX_B_IMASK (sc->sc_chan[1].hscx_mask) + + struct mbuf *sc_ibuf; /* input buffer mgmt */ + u_short sc_ilen; + u_char *sc_ib; + /* this is for the irq TX routine */ + struct mbuf *sc_obuf; /* pointer to an mbuf with TX frame */ + u_char *sc_op; /* ptr to next chunk of frame to tx */ + int sc_ol; /* length of remaining frame to tx */ + int sc_freeflag; /* m_freem mbuf if set */ + + struct mbuf *sc_obuf2; /* pointer to an mbuf with TX frame */ + int sc_freeflag2; /* m_freem mbuf if set */ + + int sc_isac_version; /* version number of ISAC */ + int sc_hscx_version; /* version number of HSCX */ + + int sc_I430state; /* I.430 state F3 .... F8 */ + + int sc_I430T3; /* I.430 Timer T3 running */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + struct callout_handle sc_T3_callout; +#endif + + int sc_I430T4; /* Timer T4 running */ +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + struct callout_handle sc_T4_callout; +#endif + + int sc_enabled; /* daemon is running */ + + int sc_ipac; /* flag, running on ipac */ + int sc_bfifolen; /* length of b channel fifos */ + +#ifdef __FreeBSD__ + + u_char (*readreg)(u_char *, u_int); + void (*writereg)(u_char *, u_int, u_int); + void (*readfifo)(void *, const void *, size_t); + void (*writefifo)(void *, const void *, size_t); + void (*clearirq)(void *); + +#define ISAC_READ(r) (*sc->readreg)(ISAC_BASE, (r)) +#define ISAC_WRITE(r,v) (*sc->writereg)(ISAC_BASE, (r), (v)); +#define ISAC_RDFIFO(b,s) (*sc->readfifo)((b), ISAC_BASE, (s)) +#define ISAC_WRFIFO(b,s) (*sc->writefifo)(ISAC_BASE, (b), (s)) + +#define HSCX_READ(n,r) (*sc->readreg)(sc->sc_chan[(n)].hscx, (r)) +#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc->sc_chan[(n)].hscx, (r), (v)) +#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)((b), sc->sc_chan[(n)].hscx, (s)) +#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc->sc_chan[(n)].hscx, (b), (s)) + +#define IPAC_READ(r) (*sc->readreg)(IPAC_BASE, (r)) +#define IPAC_WRITE(r,v) (*sc->writereg)(IPAC_BASE, (r), (v)); + +#else /* ! __FreeBSD__ */ + +#define ISIC_WHAT_ISAC 0 +#define ISIC_WHAT_HSCXA 1 +#define ISIC_WHAT_HSCXB 2 +#define ISIC_WHAT_IPAC 3 + + u_int8_t (*readreg) __P((struct isic_softc *sc, int what, bus_size_t offs)); + void (*writereg) __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); + void (*readfifo) __P((struct isic_softc *sc, int what, void *buf, size_t size)); + void (*writefifo) __P((struct isic_softc *sc, int what, const void *data, size_t size)); + void (*clearirq) __P((struct isic_softc *sc)); + +#define ISAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_ISAC, (r)) +#define ISAC_WRITE(r,v) (*sc->writereg)(sc, ISIC_WHAT_ISAC, (r), (v)) +#define ISAC_RDFIFO(b,s) (*sc->readfifo)(sc, ISIC_WHAT_ISAC, (b), (s)) +#define ISAC_WRFIFO(b,s) (*sc->writefifo)(sc, ISIC_WHAT_ISAC, (b), (s)) + +#define HSCX_READ(n,r) (*sc->readreg)(sc, ISIC_WHAT_HSCXA+(n), (r)) +#define HSCX_WRITE(n,r,v) (*sc->writereg)(sc, ISIC_WHAT_HSCXA+(n), (r), (v)) +#define HSCX_RDFIFO(n,b,s) (*sc->readfifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s)) +#define HSCX_WRFIFO(n,b,s) (*sc->writefifo)(sc, ISIC_WHAT_HSCXA+(n), (b), (s)) + +#define IPAC_READ(r) (*sc->readreg)(sc, ISIC_WHAT_IPAC, (r)) +#define IPAC_WRITE(r, v) (*sc->writereg)(sc, ISIC_WHAT_IPAC, (r), (v)) + +#endif /* __FreeBSD__ */ +}; + +/*---------------------------------------------------------------------------* + * possible I.430/ISAC states + *---------------------------------------------------------------------------*/ +enum I430states { + ST_F3, /* F3 Deactivated */ + ST_F4, /* F4 Awaiting Signal */ + ST_F5, /* F5 Identifying Input */ + ST_F6, /* F6 Synchronized */ + ST_F7, /* F7 Activated */ + ST_F8, /* F8 Lost Framing */ + ST_ILL, /* Illegal State */ + N_STATES +}; + +/*---------------------------------------------------------------------------* + * possible I.430/ISAC events + *---------------------------------------------------------------------------*/ +enum I430events { + EV_PHAR, /* PH ACTIVATE REQUEST */ + EV_T3, /* Timer 3 expired */ + EV_INFO0, /* receiving INFO0 */ + EV_RSY, /* receiving any signal */ + EV_INFO2, /* receiving INFO2 */ + EV_INFO48, /* receiving INFO4 pri 8/9 */ + EV_INFO410, /* receiving INFO4 pri 10/11 */ + EV_DR, /* Deactivate Request */ + EV_PU, /* Power UP */ + EV_DIS, /* Disconnected (only 2085) */ + EV_EI, /* Error Indication */ + EV_ILL, /* Illegal Event */ + N_EVENTS +}; + +enum I430commands { + CMD_TIM, /* Timing */ + CMD_RS, /* Reset */ + CMD_AR8, /* Activation request pri 8 */ + CMD_AR10, /* Activation request pri 10 */ + CMD_DIU, /* Deactivate Indication Upstream */ + CMD_ILL /* Illegal command */ +}; + +#define N_COMMANDS CMD_ILL + +#ifdef __FreeBSD__ + +extern struct isic_softc isic_sc[]; + +extern void isic_recover(struct isic_softc *sc); +extern int isic_realattach(struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_avma1 ( struct isa_device *dev ); +extern int isic_attach_fritzpcmcia ( struct isa_device *dev ); +extern int isic_attach_Cs0P ( struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_Dyn ( struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_s016 ( struct isa_device *dev ); +extern int isic_attach_s0163 ( struct isa_device *dev ); +extern int isic_attach_s0163P ( struct isa_device *dev ); +extern int isic_attach_s08 ( struct isa_device *dev ); +extern int isic_attach_usrtai ( struct isa_device *dev ); +extern int isic_attach_itkix1 ( struct isa_device *dev ); +extern int isic_attach_drnngo ( struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_sws ( struct isa_device *dev ); +extern int isic_attach_Eqs1pi(struct isa_device *dev, unsigned int iobase2); +extern int isic_attach_Eqs1pp(int unit, unsigned int iobase1, unsigned int iobase2); +extern void isic_bchannel_setup (int unit, int hscx_channel, int bprot, int activate ); +extern void isic_hscx_init ( struct isic_softc *sc, int hscx_channel, int activate ); +extern void isic_hscx_irq ( struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq ); +extern int isic_hscx_silence ( unsigned char *data, int len ); +extern void isic_hscx_cmd( struct isic_softc *sc, int h_chan, unsigned char cmd ); +extern void isic_hscx_waitxfw( struct isic_softc *sc, int h_chan ); +extern void isic_init_linktab ( struct isic_softc *sc ); +extern int isic_isac_init ( struct isic_softc *sc ); +extern void isic_isac_irq ( struct isic_softc *sc, int r ); +extern void isic_isac_l1_cmd ( struct isic_softc *sc, int command ); +extern void isic_next_state ( struct isic_softc *sc, int event ); +extern char *isic_printstate ( struct isic_softc *sc ); +extern int isic_probe_avma1 ( struct isa_device *dev ); +extern int isic_probe_avma1_pcmcia ( struct isa_device *dev ); +extern int isic_probe_Cs0P ( struct isa_device *dev, unsigned int iobase2); +extern int isic_probe_Dyn ( struct isa_device *dev, unsigned int iobase2); +extern int isic_probe_s016 ( struct isa_device *dev ); +extern int isic_probe_s0163 ( struct isa_device *dev ); +extern int isic_probe_s0163P ( struct isa_device *dev ); +extern int isic_probe_s08 ( struct isa_device *dev ); +extern int isic_probe_usrtai ( struct isa_device *dev ); +extern int isic_probe_itkix1 ( struct isa_device *dev ); +extern int isic_probe_drnngo ( struct isa_device *dev, unsigned int iobase2); +extern int isic_probe_sws ( struct isa_device *dev ); +extern int isic_probe_Eqs1pi(struct isa_device *dev, unsigned int iobase2); + +#else /* not FreeBSD */ + +extern void isic_recover __P((struct isic_softc *sc)); +extern int isicattach __P((int flags, struct isic_softc *sc)); +extern int isicintr __P((void *)); +extern int isicprobe __P((struct isic_attach_args *ia)); +extern int isic_attach_avma1 __P((struct isic_softc *sc)); +extern int isic_attach_s016 __P((struct isic_softc *sc)); +extern int isic_attach_s0163 __P((struct isic_softc *sc)); +extern int isic_attach_s08 __P((struct isic_softc *sc)); +extern int isic_attach_usrtai __P((struct isic_softc *sc)); +extern int isic_attach_itkix1 __P((struct isic_softc *sc)); +extern void isic_bchannel_setup __P((int unit, int hscx_channel, int bprot, int activate)); +extern void isic_hscx_init __P((struct isic_softc *sc, int hscx_channel, int activate)); +extern void isic_hscx_irq __P((struct isic_softc *sc, u_char ista, int hscx_channel, u_char ex_irq)); +extern int isic_hscx_silence __P(( unsigned char *data, int len )); +extern void isic_hscx_cmd __P(( struct isic_softc *sc, int h_chan, unsigned char cmd )); +extern void isic_hscx_waitxfw __P(( struct isic_softc *sc, int h_chan )); +extern void isic_init_linktab __P((struct isic_softc *sc)); +extern int isic_isac_init __P((struct isic_softc *sc)); +extern void isic_isac_irq __P((struct isic_softc *sc, int r)); +extern void isic_isac_l1_cmd __P((struct isic_softc *sc, int command)); +extern void isic_next_state __P((struct isic_softc *sc, int event)); +extern char * isic_printstate __P((struct isic_softc *sc)); +extern int isic_probe_avma1 __P((struct isic_attach_args *ia)); +extern int isic_probe_s016 __P((struct isic_attach_args *ia)); +extern int isic_probe_s0163 __P((struct isic_attach_args *ia)); +extern int isic_probe_s08 __P((struct isic_attach_args *ia)); +extern int isic_probe_usrtai __P((struct isic_attach_args *ia)); +extern int isic_probe_itkix1 __P((struct isic_attach_args *ia)); + +extern struct isic_softc *isic_sc[]; + +#define isic_find_sc(unit) (isic_sc[(unit)]) + +#endif /* __FreeBSD__ */ + +#endif /* I4B_L1_H_ */ diff --git a/sys/i4b/layer1/i4b_l1fsm.c b/sys/i4b/layer1/i4b_l1fsm.c new file mode 100644 index 0000000..397ce11 --- /dev/null +++ b/sys/i4b/layer1/i4b_l1fsm.c @@ -0,0 +1,546 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l1fsm.c - isdn4bsd layer 1 I.430 state machine + * -------------------------------------------------- + * + * $Id: i4b_l1fsm.c,v 1.26 1998/12/05 18:04:55 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:25:12 1998] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#else +#define NISIC 1 +#endif + +#if NISIC > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#include <machine/stdarg.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + + +static char *state_text[N_STATES] = { + "F3 Deactivated", + "F4 Awaiting Signal", + "F5 Identifying Input", + "F6 Synchronized", + "F7 Activated", + "F8 Lost Framing", + "Illegal State" +}; + +static char *event_text[N_EVENTS] = { + "EV_PHAR PH_ACT_REQ", + "EV_T3 Timer 3 expired", + "EV_INFO0 INFO0 received", + "EV_RSY Level Detected", + "EV_INFO2 INFO2 received", + "EV_INFO48 INFO4 received", + "EV_INFO410 INFO4 received", + "EV_DR Deactivate Req", + "EV_PU Power UP", + "EV_DIS Disconnected", + "EV_EI Error Ind", + "Illegal Event" +}; + +/* Function prototypes */ + +static void timer3_expired (struct isic_softc *sc); +static void T3_start (struct isic_softc *sc); +static void T3_stop (struct isic_softc *sc); +static void F_T3ex (struct isic_softc *sc); +static void timer4_expired (struct isic_softc *sc); +static void T4_start (struct isic_softc *sc); +static void T4_stop (struct isic_softc *sc); +static void F_AI8 (struct isic_softc *sc); +static void F_AI10 (struct isic_softc *sc); +static void F_I01 (struct isic_softc *sc); +static void F_I02 (struct isic_softc *sc); +static void F_I03 (struct isic_softc *sc); +static void F_I2 (struct isic_softc *sc); +static void F_ill (struct isic_softc *sc); +static void F_NULL (struct isic_softc *sc); + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 expire function + *---------------------------------------------------------------------------*/ +static void +timer3_expired(struct isic_softc *sc) +{ + if(sc->sc_I430T3) + { + DBGL1(L1_T_ERR, "timer3_expired", ("state = %s\n", isic_printstate(sc))); + sc->sc_I430T3 = 0; + + /* XXX try some recovery here XXX */ + + isic_recover(sc); + + sc->sc_init_tries++; /* increment retry count */ + +/*XXX*/ if(sc->sc_init_tries > 4) + { + int s = SPLI4B(); + + sc->sc_init_tries = 0; + + if(sc->sc_obuf2 != NULL) + { + i4b_Dfreembuf(sc->sc_obuf2); + sc->sc_obuf2 = NULL; + } + if(sc->sc_obuf != NULL) + { + i4b_Dfreembuf(sc->sc_obuf); + sc->sc_obuf = NULL; + sc->sc_freeflag = 0; + sc->sc_op = NULL; + sc->sc_ol = 0; + } + + splx(s); + + MPH_Status_Ind(sc->sc_unit, STI_NOL1ACC, 0); + } + + isic_next_state(sc, EV_T3); + } + else + { + DBGL1(L1_T_ERR, "timer3_expired", ("expired without starting it ....\n")); + } +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 start + *---------------------------------------------------------------------------*/ +static void +T3_start(struct isic_softc *sc) +{ + DBGL1(L1_T_MSG, "T3_start", ("state = %s\n", isic_printstate(sc))); + sc->sc_I430T3 = 1; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + sc->sc_T3_callout = timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz); +#else + timeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, 2*hz); +#endif +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 stop + *---------------------------------------------------------------------------*/ +static void +T3_stop(struct isic_softc *sc) +{ + DBGL1(L1_T_MSG, "T3_stop", ("state = %s\n", isic_printstate(sc))); + + sc->sc_init_tries = 0; /* init connect retry count */ + + if(sc->sc_I430T3) + { + sc->sc_I430T3 = 0; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc, sc->sc_T3_callout); +#else + untimeout((TIMEOUT_FUNC_T)timer3_expired,(struct isic_softc *)sc); +#endif + } +} + +/*---------------------------------------------------------------------------* + * I.430 Timer T3 expiry + *---------------------------------------------------------------------------*/ +static void +F_T3ex(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_T3ex", ("FSM function F_T3ex executing\n")); + PH_Deact_Ind(sc->sc_unit); +} + +/*---------------------------------------------------------------------------* + * Timer T4 expire function + *---------------------------------------------------------------------------*/ +static void +timer4_expired(struct isic_softc *sc) +{ + if(sc->sc_I430T4) + { + DBGL1(L1_T_ERR, "timer4_expired", ("state = %s\n", isic_printstate(sc))); + sc->sc_I430T4 = 0; + MPH_Status_Ind(sc->sc_unit, STI_PDEACT, 0); + } + else + { + DBGL1(L1_T_ERR, "timer4_expired", ("expired without starting it ....\n")); + } +} + +/*---------------------------------------------------------------------------* + * Timer T4 start + *---------------------------------------------------------------------------*/ +static void +T4_start(struct isic_softc *sc) +{ + DBGL1(L1_T_MSG, "T4_start", ("state = %s\n", isic_printstate(sc))); + sc->sc_I430T4 = 1; + +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + sc->sc_T4_callout = timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz); +#else + timeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, hz); +#endif +} + +/*---------------------------------------------------------------------------* + * Timer T4 stop + *---------------------------------------------------------------------------*/ +static void +T4_stop(struct isic_softc *sc) +{ + DBGL1(L1_T_MSG, "T4_stop", ("state = %s\n", isic_printstate(sc))); + + if(sc->sc_I430T4) + { + sc->sc_I430T4 = 0; +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc, sc->sc_T4_callout); +#else + untimeout((TIMEOUT_FUNC_T)timer4_expired,(struct isic_softc *)sc); +#endif + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received AI8 + *---------------------------------------------------------------------------*/ +static void +F_AI8(struct isic_softc *sc) +{ + T4_stop(sc); + + DBGL1(L1_F_MSG, "F_AI8", ("FSM function F_AI8 executing\n")); + + PH_Act_Ind(sc->sc_unit); + + T3_stop(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO4_8; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received AI10 + *---------------------------------------------------------------------------*/ +static void +F_AI10(struct isic_softc *sc) +{ + T4_stop(sc); + + DBGL1(L1_F_MSG, "F_AI10", ("FSM function F_AI10 executing\n")); + + PH_Act_Ind(sc->sc_unit); + + T3_stop(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO4_10; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in states F3 .. F5 + *---------------------------------------------------------------------------*/ +static void +F_I01(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_I01", ("FSM function F_I01 executing\n")); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in state F6 + *---------------------------------------------------------------------------*/ +static void +F_I02(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_I02", ("FSM function F_I02 executing\n")); + + PH_Deact_Ind(sc->sc_unit); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO 0 in state F7 or F8 + *---------------------------------------------------------------------------*/ +static void +F_I03(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_I03", ("FSM function F_I03 executing\n")); + + PH_Deact_Ind(sc->sc_unit); + + T4_start(sc); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO0; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } +} + +/*---------------------------------------------------------------------------* + * FSM function: activate request + *---------------------------------------------------------------------------*/ +static void +F_AR(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_AR", ("FSM function F_AR executing\n")); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO1_8; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_TE; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } + + isic_isac_l1_cmd(sc, CMD_AR8); + + T3_start(sc); +} + +/*---------------------------------------------------------------------------* + * FSM function: received INFO2 + *---------------------------------------------------------------------------*/ +static void +F_I2(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_I2", ("FSM function F_I2 executing\n")); + + if(sc->sc_trace & TRACE_I) + { + i4b_trace_hdr_t hdr; + char info = INFO2; + + hdr.unit = sc->sc_unit; + hdr.type = TRC_CH_I; + hdr.dir = FROM_NT; + hdr.count = 0; + MICROTIME(hdr.time); + MPH_Trace_Ind(&hdr, 1, &info); + } + +} + +/*---------------------------------------------------------------------------* + * illegal state default action + *---------------------------------------------------------------------------*/ +static void +F_ill(struct isic_softc *sc) +{ + DBGL1(L1_F_ERR, "F_ill", ("FSM function F_ill executing\n")); +} + +/*---------------------------------------------------------------------------* + * No action + *---------------------------------------------------------------------------*/ +static void +F_NULL(struct isic_softc *sc) +{ + DBGL1(L1_F_MSG, "F_NULL", ("FSM function F_NULL executing\n")); +} + + +/*---------------------------------------------------------------------------* + * layer 1 state transition table + *---------------------------------------------------------------------------*/ +struct isic_state_tab { + void (*func) (struct isic_softc *sc); /* function to execute */ + int newstate; /* next state */ +} isic_state_tab[N_EVENTS][N_STATES] = { + +/* STATE: F3 F4 F5 F6 F7 F8 ILLEGAL STATE */ +/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* EV_PHAR x*/ {{F_AR, ST_F4}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_ill, ST_ILL}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_T3 x*/ {{F_NULL, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_T3ex, ST_F3}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_INFO0 */ {{F_I01, ST_F3}, {F_I01, ST_F4}, {F_I01, ST_F5}, {F_I02, ST_F3}, {F_I03, ST_F3}, {F_I03, ST_F3}, {F_ill, ST_ILL}}, +/* EV_RSY x*/ {{F_NULL, ST_F3}, {F_NULL, ST_F5}, {F_NULL, ST_F5}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_INFO2 */ {{F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_I2, ST_F6}, {F_ill, ST_ILL}}, +/* EV_INFO48*/ {{F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_AI8, ST_F7}, {F_NULL, ST_F7}, {F_AI8, ST_F7}, {F_ill, ST_ILL}}, +/* EV_INFO41*/ {{F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_AI10, ST_F7}, {F_NULL, ST_F7}, {F_AI10, ST_F7}, {F_ill, ST_ILL}}, +/* EV_DR */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_PU */ {{F_NULL, ST_F3}, {F_NULL, ST_F4}, {F_NULL, ST_F5}, {F_NULL, ST_F6}, {F_NULL, ST_F7}, {F_NULL, ST_F8}, {F_ill, ST_ILL}}, +/* EV_DIS */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_EI */ {{F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_NULL, ST_F3}, {F_ill, ST_ILL}}, +/* EV_ILL */ {{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}} +}; + +/*---------------------------------------------------------------------------* + * event handler + *---------------------------------------------------------------------------*/ +void +isic_next_state(struct isic_softc *sc, int event) +{ + int currstate, newstate; + + if(event >= N_EVENTS) + panic("i4b_l1fsm.c: event >= N_EVENTS\n"); + + currstate = sc->sc_I430state; + + if(currstate >= N_STATES) + panic("i4b_l1fsm.c: currstate >= N_STATES\n"); + + newstate = isic_state_tab[event][currstate].newstate; + + if(newstate >= N_STATES) + panic("i4b_l1fsm.c: newstate >= N_STATES\n"); + + DBGL1(L1_F_MSG, "isic_next_state", ("FSM event [%s]: [%s => %s]\n", event_text[event], + state_text[currstate], + state_text[newstate])); + + (*isic_state_tab[event][currstate].func)(sc); + + if(newstate == ST_ILL) + { + newstate = ST_F3; + DBGL1(L1_F_ERR, "isic_next_state", ("FSM Illegal State ERROR, oldstate = %s, newstate = %s, event = %s!\n", + state_text[currstate], + state_text[newstate], + event_text[event])); + } + + sc->sc_I430state = newstate; +} + +/*---------------------------------------------------------------------------* + * return pointer to current state description + *---------------------------------------------------------------------------*/ +char * +isic_printstate(struct isic_softc *sc) +{ + return((char *) state_text[sc->sc_I430state]); +} + +#endif /* NISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_sws.c b/sys/i4b/layer1/i4b_sws.c new file mode 100644 index 0000000..c5182b4 --- /dev/null +++ b/sys/i4b/layer1/i4b_sws.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 1998 German Tischler. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * Card format: + * + * iobase + 0 : reset on (0x03) + * iobase + 1 : reset off (0x0) + * iobase + 2 : isac read/write + * iobase + 3 : hscx read/write ( offset 0-0x3f hscx0 , + * offset 0x40-0x7f hscx1 ) + * iobase + 4 : offset for indirect adressing + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for SWS cards + * ==================================================== + * + * EXPERIMENTAL !!!! + * ================= + * + * $Id: i4b_sws.c,v 1.12 1998/12/18 09:32:45 hm Exp $ + * + * last edit-date: [Sun Dec 13 10:49:25 1998] + * + * -hm adding driver to i4b + * -hm adjustments for FreeBSD < 2.2.6, no PnP support yet + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) + +#include "isic.h" +#include "opt_i4b.h" + +#else + +#define NISIC 1 + +#endif + +#if defined (SEDLBAUER) && NISIC > 0 + +#define SWS_RESON 0 /* reset on */ +#define SWS_RESOFF 1 /* reset off */ +#define SWS_ISAC 2 /* ISAC */ +#define SWS_HSCX0 3 /* HSCX0 */ +#define SWS_RW 4 /* indirect access register */ +#define SWS_HSCX1 5 /* this is for fakeing that we mean hscx1, though */ + /* access is done through hscx0 */ + +#define SWS_REGS 8 /* we use an area of 8 bytes for io */ + +#define SWS_BASE(X) ((unsigned int)X&~(SWS_REGS-1)) +#define SWS_PART(X) ((unsigned int)X& (SWS_REGS-1)) +#define SWS_ADDR(X) ((SWS_PART(X) == SWS_ISAC) ? (SWS_BASE(X)+SWS_ISAC) : (SWS_BASE(X)+SWS_HSCX0) ) +#define SWS_REG(X,Y) ((SWS_PART(X) != SWS_HSCX1) ? Y : (Y+0x40) ) +#define SWS_IDO(X) (SWS_BASE(X)+SWS_RW) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#ifndef __FreeBSD__ +static u_int8_t sws_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void sws_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void sws_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void sws_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +void isic_attach_sws __P((struct isic_softc *sc)); +#endif + +/*---------------------------------------------------------------------------* + * SWS P&P ISAC get fifo routine + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +static void +sws_read_fifo(void *buf, const void *base, size_t len) +{ + outb(SWS_IDO(base),SWS_REG(base,0)); + insb(SWS_ADDR(base),buf,len); +} + +#else + +static void +sws_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, SWS_RW, 0); + bus_space_read_multi_1(t, h, SWS_ISAC, buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, SWS_RW, 0); + bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, SWS_RW, 0x40); + bus_space_read_multi_1(t, h, SWS_HSCX0, buf, size); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * SWS P&P ISAC put fifo routine + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +static void +sws_write_fifo(void *base, const void *buf, size_t len) +{ + outb (SWS_IDO(base),SWS_REG(base,0)); + outsb(SWS_ADDR(base),buf,len); +} + +#else + +static void +sws_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, SWS_RW, 0); + bus_space_write_multi_1(t, h, SWS_ISAC, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, SWS_RW, 0); + bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, SWS_RW, 0x40); + bus_space_write_multi_1(t, h, SWS_HSCX0, (u_int8_t*)buf, size); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * SWS P&P ISAC put register routine + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ + +static void +sws_write_reg(u_char *base, u_int offset, u_int v) +{ + outb(SWS_IDO(base),SWS_REG(base,offset)); + outb(SWS_ADDR(base),v); +} + +#else + +static void +sws_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, SWS_RW, offs); + bus_space_write_1(t, h, SWS_ISAC, data); + break; + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, SWS_RW, offs); + bus_space_write_1(t, h, SWS_HSCX0, data); + break; + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, SWS_RW, 0x40+offs); + bus_space_write_1(t, h, SWS_HSCX0, data); + break; + } +} + +#endif + +/*---------------------------------------------------------------------------* + * SWS P&P ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +sws_read_reg(u_char *base, u_int offset) +{ + outb(SWS_IDO(base),SWS_REG(base,offset)); + return inb(SWS_ADDR(base)); +} + +#else + +static u_int8_t +sws_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + switch (what) { + case ISIC_WHAT_ISAC: + bus_space_write_1(t, h, SWS_RW, offs); + return bus_space_read_1(t, h, SWS_ISAC); + case ISIC_WHAT_HSCXA: + bus_space_write_1(t, h, SWS_RW, offs); + return bus_space_read_1(t, h, SWS_HSCX0); + case ISIC_WHAT_HSCXB: + bus_space_write_1(t, h, SWS_RW, 0x40+offs); + return bus_space_read_1(t, h, SWS_HSCX0); + } + return 0; +} + +#endif + +#ifdef __FreeBSD__ + +/* attach callback routine */ + +int +isic_attach_sws(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* fill in isic_softc structure */ + + sc->readreg = sws_read_reg; + sc->writereg = sws_write_reg; + sc->readfifo = sws_read_fifo; + sc->writefifo = sws_write_fifo; + sc->clearirq = NULL; + sc->sc_unit = dev->id_unit; + sc->sc_irq = dev->id_irq; + sc->sc_port = dev->id_iobase; + sc->sc_cardtyp = CARD_TYPEP_SWS; + sc->sc_bustyp = BUS_TYPE_IOM2; + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + dev->id_msize = 0; + + ISAC_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_ISAC); + HSCX_A_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX0); + HSCX_B_BASE = (caddr_t) (((u_int) sc->sc_port) + SWS_HSCX1); + + /* + * Read HSCX A/B VSTR. Expected value for the SWS PnP card is + * 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for SWS PnP\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + /* reset card */ + + outb( ((u_int) sc->sc_port) + SWS_RESON , 0x3); + DELAY(SEC_DELAY / 5); + outb( ((u_int) sc->sc_port) + SWS_RESOFF, 0); + DELAY(SEC_DELAY / 5); + + return(1); +} + +#else /* !__FreeBSD__ */ + +void +isic_attach_sws(struct isic_softc *sc) +{ + /* setup access routines */ + + sc->readreg = sws_read_reg; + sc->writereg = sws_write_reg; + + sc->readfifo = sws_read_fifo; + sc->writefifo = sws_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_SWS; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* + * Read HSCX A/B VSTR. Expected value for the SWS PnP card is + * 0x05 ( = version 2.1 ) in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("%s: HSCX VSTR test failed for SWS PnP\n", + sc->sc_dev.dv_xname); + printf("%s: HSC0: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(0, H_VSTR)); + printf("%s: HSC1: VSTR: %#x\n", + sc->sc_dev.dv_xname, HSCX_READ(1, H_VSTR)); + return; + } + + /* reset card */ + { + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, SWS_RESON, 0x3); + DELAY(SEC_DELAY / 5); + bus_space_write_1(t, h, SWS_RESOFF, 0); + DELAY(SEC_DELAY / 5); + } +} + +#endif /* !__FreeBSD__ */ + +#endif /* defined(SEDLBAUER) && NISIC > 0 */ diff --git a/sys/i4b/layer1/i4b_tel_s016.c b/sys/i4b/layer1/i4b_tel_s016.c new file mode 100644 index 0000000..f77a3c1 --- /dev/null +++ b/sys/i4b/layer1/i4b_tel_s016.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16 and clones + * ================================================================= + * + * $Id: i4b_tel_s016.c,v 1.12 1998/12/05 18:04:56 hm Exp $ + * + * last edit-date: [Fri Dec 4 10:40:17 1998] + * + * -hm clean up + * -hm checked with a Creatix ISDN-S0 (PCB version: mp 130.1) + * -hm more cleanup + * -hm NetBSD patches from Martin + * -hm converting asm -> C + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(TEL_S0_16) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <machine/md_var.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 }; + +#ifndef __FreeBSD__ +static u_int8_t tels016_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void tels016_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void tels016_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void tels016_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16 write register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels016_write_reg(u_char *base, u_int i, u_int v) +{ + if(i & 0x01) + i |= 0x200; + base[i] = v; +} + +#else + +static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 }; + +static void +tels016_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + + offs += offset[what]; + if (offs & 0x01) + offs |= 0x200; + + bus_space_write_1(t, h, offs, data); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16 read register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +tels016_read_reg(u_char *base, u_int i) +{ + if(i & 0x1) + i |= 0x200; + return(base[i]); +} + +#else + +static u_int8_t +tels016_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + + offs += offset[what]; + + if(offs & 0x01) + offs |= 0x200; + + return bus_space_read_1(t, h, offs); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16 fifo read/write routines + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels016_memcpyb(void *to, const void *from, size_t len) +{ + for(;len > 0; len--) + *((unsigned char *)to)++ = *((unsigned char *)from)++; +} + +#else + +static void +tels016_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + bus_space_write_region_1(t, h, offset[what], data, size); +} + +static void +tels016_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[1].t; + bus_space_handle_t h = sc->sc_maps[1].h; + bus_space_read_region_1(t, h, offset[what], buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_s016 - probe for Teles S0/16 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_s016(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + u_char byte; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + if((intr_no[ffs(dev->id_irq) - 1]) == 1) + { + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + } + sc->sc_irq = dev->id_irq; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0xd80: + case 0xe80: + case 0xf80: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16!\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + /* check if valid memory addr */ + + switch((unsigned int)kvtop(dev->id_maddr)) + { + case 0xc0000: + case 0xc2000: + case 0xc4000: + case 0xc6000: + case 0xc8000: + case 0xca000: + case 0xcc000: + case 0xce000: + case 0xd0000: + case 0xd2000: + case 0xd4000: + case 0xd6000: + case 0xd8000: + case 0xda000: + case 0xdc000: + case 0xde000: + break; + + default: + printf("isic%d: Error, invalid mem addr 0x%lx for Teles S0/16!\n", + dev->id_unit, kvtop(dev->id_maddr)); + return(0); + break; + } + sc->sc_vmem_addr = (caddr_t) dev->id_maddr; + dev->id_msize = 0x1000; + + /* check card signature */ + + if((byte = inb(sc->sc_port)) != 0x51) + { + printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16!\n", + dev->id_unit, byte); + return(0); + } + + if((byte = inb(sc->sc_port + 1)) != 0x93) + { + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16!\n", + dev->id_unit, byte); + return(0); + } + + byte = inb(sc->sc_port + 2); + + if((byte != 0x1e) && (byte != 0x1f)) + { + printf("isic%d: Error, signature 3 0x%x != 0x1e or 0x1f for Teles S0/16!\n", + dev->id_unit, byte); + return(0); + } + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels016_read_reg; + sc->writereg = tels016_write_reg; + + sc->readfifo = tels016_memcpyb; + sc->writefifo = tels016_memcpyb; + + /* setup card type */ + + sc->sc_cardtyp= CARD_TYPEP_16; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC base addr */ + + ISAC_BASE = (caddr_t) ((dev->id_maddr) + 0x100); + + /* setup HSCX base addr */ + + HSCX_A_BASE = (caddr_t) ((dev->id_maddr) + 0x180); + HSCX_B_BASE = (caddr_t) ((dev->id_maddr) + 0x1c0); + + return (1); +} + +#else + +int +isic_probe_s016(struct isic_attach_args *ia) +{ + bus_space_tag_t t = ia->ia_maps[0].t; + bus_space_handle_t h = ia->ia_maps[0].h; + u_int8_t b0, b1, b2; + + b0 = bus_space_read_1(t, h, 0); + b1 = bus_space_read_1(t, h, 1); + b2 = bus_space_read_1(t, h, 2); + + if (b0 == 0x51 && b1 == 0x93 && (b2 == 0x1e || b2 == 0x1f)) + return 1; + + return 0; +} +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_s016 - attach Teles S0/16 and compatibles + *---------------------------------------------------------------------------*/ +int +#ifdef __FreeBSD__ +isic_attach_s016(struct isa_device *dev) +#else +isic_attach_s016(struct isic_softc *sc) +#endif +{ + +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[dev->id_unit]; +#endif + + u_long irq; + +#ifndef __FreeBSD__ + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels016_read_reg; + sc->writereg = tels016_write_reg; + + sc->readfifo = tels016_read_fifo; + sc->writefifo = tels016_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp= CARD_TYPEP_16; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + +#endif + +#ifdef __FreeBSD__ + if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1) + { + printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + } +#else + irq = intr_no[sc->sc_irq]; +#endif + + /* configure IRQ */ + +#ifdef __FreeBSD__ + irq |= ((u_long) sc->sc_vmem_addr) >> 9; + + DELAY(SEC_DELAY / 10); + outb(sc->sc_port + 4, irq); + + DELAY(SEC_DELAY / 10); + outb(sc->sc_port + 4, irq | 0x01); + + DELAY(SEC_DELAY / 5); + + /* set card bit off */ + + sc->sc_vmem_addr[0x80] = 0; + DELAY(SEC_DELAY / 5); + + /* set card bit on */ + + sc->sc_vmem_addr[0x80] = 1; + DELAY(SEC_DELAY / 5); + +#else + + irq |= ((sc->sc_maddr >> 9) & 0x000000f0); + + DELAY(SEC_DELAY / 10); + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq); + + DELAY(SEC_DELAY / 10); + bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, 4, irq | 0x01); + + DELAY(SEC_DELAY / 5); + + /* set card bit off */ + + bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 0); + DELAY(SEC_DELAY / 5); + + /* set card bit on */ + + bus_space_write_1(sc->sc_maps[1].t, sc->sc_maps[1].h, 0x80, 1); + DELAY(SEC_DELAY / 5); +#endif + + return (1); +} + +#endif /* ISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_tel_s0163.c b/sys/i4b/layer1/i4b_tel_s0163.c new file mode 100644 index 0000000..5fdd329 --- /dev/null +++ b/sys/i4b/layer1/i4b_tel_s0163.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/16.3 + * ======================================================== + * + * $Id: i4b_tel_s0163.c,v 1.15 1998/12/05 18:04:58 hm Exp $ + * + * last edit-date: [Fri Dec 4 10:40:58 1998] + * + * -hm clean up + * -hm more cleanup + * -hm NetBSD patches from Martin + * -hm VSTR detection for older 16.3 cards + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(TEL_S0_16_3) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +static u_char intr_no[] = { 1, 1, 0, 2, 4, 6, 1, 1, 1, 0, 8, 10, 12, 1, 1, 14 }; + +#ifndef __FreeBSD__ +static u_int8_t tels0163_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void tels0163_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void tels0163_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void tels0163_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 read fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163_read_fifo(void *buf, const void *base, size_t len) +{ + insb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +tels0163_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_read_multi_1(t, h, o + 0x1e, buf, size); +} + +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 write fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163_write_fifo(void *base, const void *buf, size_t len) +{ + outsb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +tels0163_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_multi_1(t, h, o + 0x1e, (u_int8_t*)buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 ISAC put register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163_write_reg(u_char *base, u_int offset, u_int v) +{ + outb((int)base + offset, (u_char)v); +} + +#else + +static void +tels0163_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_1(t, h, o + offs - 0x20, data); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 ISAC get register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +tels0163_read_reg(u_char *base, u_int offset) +{ + return (inb((int)base + offset)); +} + +#else + +static u_int8_t +tels0163_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + return bus_space_read_1(t, h, o + offs - 0x20); +} + +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_s0163 - probe for Teles S0/16.3 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_s0163(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + u_char byte; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3!", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + if((intr_no[ffs(dev->id_irq) - 1]) == 1) + { + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3!", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + + dev->id_msize = 0; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0xd80: + case 0xe80: + case 0xf80: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3!", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + if((byte = inb(sc->sc_port)) != 0x51) + { + printf("isic%d: Error, signature 1 0x%x != 0x51 for Teles S0/16.3!", + dev->id_unit, byte); + return(0); + } + + if((byte = inb(sc->sc_port + 1)) != 0x93) + { + printf("isic%d: Error, signature 2 0x%x != 0x93 for Teles S0/16.3!", + dev->id_unit, byte); + return(0); + } + + if((byte = inb(sc->sc_port + 2)) != 0x1c) + { + printf("isic%d: Error, signature 3 0x%x != 0x1c for Teles S0/16.3!", + dev->id_unit, byte); + return(0); + } + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels0163_read_reg; + sc->writereg = tels0163_write_reg; + + sc->readfifo = tels0163_read_fifo; + sc->writefifo = tels0163_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp= CARD_TYPEP_16_3; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + switch(dev->id_iobase) + { + case 0xd80: + ISAC_BASE = (caddr_t) 0x960; + HSCX_A_BASE = (caddr_t) 0x160; + HSCX_B_BASE = (caddr_t) 0x560; + break; + + case 0xe80: + ISAC_BASE = (caddr_t) 0xa60; + HSCX_A_BASE = (caddr_t) 0x260; + HSCX_B_BASE = (caddr_t) 0x660; + break; + + case 0xf80: + ISAC_BASE = (caddr_t) 0xb60; + HSCX_A_BASE = (caddr_t) 0x360; + HSCX_B_BASE = (caddr_t) 0x760; + break; + } + + /* + * Read HSCX A/B VSTR. Expected value for the S0/16.3 card is + * 0x05 or 0x04 (for older 16.3's) in the least significant bits. + */ + + if( (((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(0, H_VSTR) & 0xf) != 0x4)) || + (((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) && + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x4)) ) + { + printf("isic%d: HSCX VSTR test failed for Teles S0/16.3\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +#else + +int +isic_probe_s0163(struct isic_attach_args *ia) +{ + bus_space_tag_t t = ia->ia_maps[0].t; + bus_space_handle_t h = ia->ia_maps[0].h; + u_int8_t b0, b1, b2; + + b0 = bus_space_read_1(t, h, 0); + b1 = bus_space_read_1(t, h, 1); + b2 = bus_space_read_1(t, h, 2); + + if (b0 == 0x51 && b1 == 0x93 && b2 == 0x1c) + return 1; + + return 0; +} +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_s0163 - attach Teles S0/16.3 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_attach_s0163(struct isa_device *dev) +{ + u_char irq; + + if((irq = intr_no[ffs(dev->id_irq) - 1]) == 1) + { + printf("isic%d: Attach error, invalid IRQ [%d] specified for Teles S0/16.3!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + } + + /* configure IRQ */ + + DELAY(SEC_DELAY / 10); + outb(dev->id_iobase + 4, irq); + + DELAY(SEC_DELAY / 10); + outb(dev->id_iobase + 4, irq | 0x01); + + return (1); +} + +#else + +int +isic_attach_s0163(struct isic_softc *sc) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + u_int8_t irq = intr_no[sc->sc_irq]; + + /* configure IRQ */ + + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 4, irq); + + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 4, irq | 0x01); + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels0163_read_reg; + sc->writereg = tels0163_write_reg; + + sc->readfifo = tels0163_read_fifo; + sc->writefifo = tels0163_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp= CARD_TYPEP_16_3; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + return (1); +} +#endif + +#endif /* ISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_tel_s08.c b/sys/i4b/layer1/i4b_tel_s08.c new file mode 100644 index 0000000..6115e12 --- /dev/null +++ b/sys/i4b/layer1/i4b_tel_s08.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 1996 Arne Helme. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0/8 and clones + * ================================================================ + * + * $Id: i4b_tel_s08.c,v 1.13 1998/12/05 18:04:59 hm Exp $ + * + * last edit-date: [Fri Dec 4 10:39:12 1998] + * + * -hm clean up + * -hm more cleanup + * -hm NetBSD patches from Martin + * -hm making it finally work (checked with board revision 1.2) + * -hm converting asm -> C + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(TEL_S0_8) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <machine/md_var.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#ifndef __FreeBSD__ +static u_int8_t tels08_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void tels08_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void tels08_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +static void tels08_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/8 write register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels08_write_reg(u_char *base, u_int i, u_int v) +{ + if(i & 0x01) + i |= 0x200; + base[i] = v; +} + +#else + +static const bus_size_t offset[] = { 0x100, 0x180, 0x1c0 }; + +static void +tels08_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + + offs += offset[what]; + + if (offs & 0x01) + offs |= 0x200; + + bus_space_write_1(t, h, offs, data); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/8 read register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +tels08_read_reg(u_char *base, u_int i) +{ + if(i & 0x1) + i |= 0x200; + return(base[i]); +} + +#else + +static u_int8_t +tels08_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + + offs += offset[what]; + + if (offs & 0x01) + offs |= 0x200; + + return bus_space_read_1(t, h, offs); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/8 fifo read/write access + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels08_memcpyb(void *to, const void *from, size_t len) +{ + for(;len > 0; len--) + *((unsigned char *)to)++ = *((unsigned char *)from)++; +} + +#else + +static void +tels08_write_fifo(struct isic_softc *sc, int what, const void *data, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_region_1(t, h, offset[what], data, size); +} + +static void +tels08_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_read_region_1(t, h, offset[what], buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_s08 - probe for Teles S0/8 and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +int +isic_probe_s08(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/8!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq)-1) + { + case 2: + case 9: /* XXX */ + case 3: + case 4: + case 5: + case 6: + case 7: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/8!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if we got an iobase */ + + if(dev->id_iobase > 0) + { + printf("isic%d: Error, iobase specified for Teles S0/8!\n", + dev->id_unit); + return(0); + } + + /* check if inside memory range of 0xA0000 .. 0xDF000 */ + + if( (kvtop(dev->id_maddr) < 0xa0000) || + (kvtop(dev->id_maddr) > 0xdf000) ) + { + printf("isic%d: Error, mem addr 0x%lx outside 0xA0000-0xDF000 for Teles S0/8!\n", + dev->id_unit, kvtop(dev->id_maddr)); + return(0); + } + + sc->sc_vmem_addr = (caddr_t) dev->id_maddr; + dev->id_msize = 0x1000; + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = tels08_read_reg; + sc->writereg = tels08_write_reg; + + sc->readfifo = tels08_memcpyb; + sc->writefifo = tels08_memcpyb; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_8; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC base addr */ + + ISAC_BASE = (caddr_t)((dev->id_maddr) + 0x100); + + /* setup HSCX base addr */ + + HSCX_A_BASE = (caddr_t)((dev->id_maddr) + 0x180); + HSCX_B_BASE = (caddr_t)((dev->id_maddr) + 0x1c0); + + return (1); +} + +#else + +int +isic_probe_s08(struct isic_attach_args *ia) +{ + /* no real sensible probe is easy - write to fifo memory + and read back to verify there is memory doesn't work, + because you talk to tx fifo and rcv fifo. So, just check + HSCX version, which at least fails if no card present + at the given location. */ + bus_space_tag_t t = ia->ia_maps[0].t; + bus_space_handle_t h = ia->ia_maps[0].h; + u_int8_t v1, v2; + + /* HSCX A VSTR */ + v1 = bus_space_read_1(t, h, offset[1] + H_VSTR) & 0x0f; + if (v1 != HSCX_VA1 && v1 != HSCX_VA2 && v1 != HSCX_VA3 && v1 != HSCX_V21) + return 0; + + /* HSCX B VSTR */ + v2 = bus_space_read_1(t, h, offset[2] + H_VSTR) & 0x0f; + if (v2 != HSCX_VA1 && v2 != HSCX_VA2 && v2 != HSCX_VA3 && v2 != HSCX_V21) + return 0; + + /* both HSCX channels should have the same version... */ + if (v1 != v2) + return 0; + + return 1; +} +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_s08 - attach Teles S0/8 and compatibles + *---------------------------------------------------------------------------*/ +int +#ifdef __FreeBSD__ +isic_attach_s08(struct isa_device *dev) +#else +isic_attach_s08(struct isic_softc *sc) +#endif +{ +#ifdef __FreeBSD__ + struct isic_softc *sc = &isic_sc[dev->id_unit]; +#else + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; +#endif + + /* set card off */ + +#ifdef __FreeBSD__ + sc->sc_vmem_addr[0x80] = 0; +#else + bus_space_write_1(t, h, 0x80, 0); +#endif + + DELAY(SEC_DELAY / 5); + + /* set card on */ + +#ifdef __FreeBSD__ + sc->sc_vmem_addr[0x80] = 1; +#else + bus_space_write_1(t, h, 0x80, 1); +#endif + + DELAY(SEC_DELAY / 5); + +#ifndef __FreeBSD__ + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = tels08_read_reg; + sc->writereg = tels08_write_reg; + sc->readfifo = tels08_read_fifo; + sc->writefifo = tels08_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_8; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM1; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + +#endif + + return (1); +} + +#endif /* ISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_tel_s0P.c b/sys/i4b/layer1/i4b_tel_s0P.c new file mode 100644 index 0000000..9bccd77 --- /dev/null +++ b/sys/i4b/layer1/i4b_tel_s0P.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 1997 Andrew Gordon. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic - I4B Siemens ISDN Chipset Driver for Teles S0 PnP + * ======================================================= + * + * EXPERIMENTAL !!! + * ================ + * + * $Id: i4b_tel_s0P.c,v 1.12 1998/12/13 09:52:34 hm Exp $ + * + * last edit-date: [Thu Dec 10 07:11:15 1998] + * + * -hm rudimentary PnP support, hint from Andrew Gordon + * -hm more cleanup + * -hm NetBSD patches from Martin + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(TEL_S0_16_3_P) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_mbuf.h> + +#ifndef __FreeBSD__ +static u_int8_t tels0163P_read_reg __P((struct isic_softc *sc, int what, bus_size_t offs)); +static void tels0163P_write_reg __P((struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data)); +static void tels0163P_read_fifo __P((struct isic_softc *sc, int what, void *buf, size_t size)); +static void tels0163P_write_fifo __P((struct isic_softc *sc, int what, const void *data, size_t size)); +void isic_attach_s0163P __P((struct isic_softc *sc)); +#endif + + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 PnP read fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163P_read_fifo(void *buf, const void *base, size_t len) +{ + insb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +tels0163P_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_read_multi_1(t, h, o + 0x3e, buf, size); +} + +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 PnP write fifo routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163P_write_fifo(void *base, const void *buf, size_t len) +{ + outsb((int)base + 0x3e, (u_char *)buf, (u_int)len); +} + +#else + +static void +tels0163P_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_multi_1(t, h, o + 0x3e, (u_int8_t*)buf, size); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 PnP write register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static void +tels0163P_write_reg(u_char *base, u_int offset, u_int v) +{ + outb((int)base + offset, (u_char)v); +} + +#else + +static void +tels0163P_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + bus_space_write_1(t, h, o + offs, data); +} +#endif + +/*---------------------------------------------------------------------------* + * Teles S0/16.3 PnP read register routine + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ + +static u_char +tels0163P_read_reg(u_char *base, u_int offset) +{ + return (inb((int)base + offset)); +} + +#else + +static u_int8_t +tels0163P_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[what+1].t; + bus_space_handle_t h = sc->sc_maps[what+1].h; + bus_size_t o = sc->sc_maps[what+1].offset; + return bus_space_read_1(t, h, o + offs); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_probe_s0163P - probe for Teles S0/16.3 PnP and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_probe_s0163P(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= ISIC_MAXUNIT for Teles S0/16.3 PnP!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + switch(ffs(dev->id_irq) - 1) + { + case 3: + case 5: + case 7: + case 10: + case 11: + case 12: + break; + + default: + printf("isic%d: Error, invalid IRQ [%d] specified for Teles S0/16.3 PnP!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + break; + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for Teles S0/16.3 PnP!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + dev->id_msize = 0; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0x580: + case 0x500: + case 0x680: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for Teles S0/16.3 PnP!\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels0163P_read_reg; + sc->writereg = tels0163P_write_reg; + + sc->readfifo = tels0163P_read_fifo; + sc->writefifo = tels0163P_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_163P; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + switch(dev->id_iobase) + { + case 0x580: + ISAC_BASE = (caddr_t) 0x580 - 0x20; + HSCX_A_BASE = (caddr_t) 0x180 - 0x20; + HSCX_B_BASE = (caddr_t) 0x180; + break; + + case 0x500: + ISAC_BASE = (caddr_t) 0x500 - 0x20; + HSCX_A_BASE = (caddr_t) 0x100 - 0x20; + HSCX_B_BASE = (caddr_t) 0x100; + break; + + case 0x680: + ISAC_BASE = (caddr_t) 0x680 - 0x20; + HSCX_A_BASE = (caddr_t) 0x280 - 0x20; + HSCX_B_BASE = (caddr_t) 0x280; + break; + } + + /* + * Read HSCX A/B VSTR. Expected value for the S0/16.3 PnP card is + * 0x05 in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for Teles S0/16.3 PnP\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} +#endif + +/*---------------------------------------------------------------------------* + * isic_attach_s0163P - attach Teles S0/16.3 PnP and compatibles + *---------------------------------------------------------------------------*/ +#ifdef __FreeBSD__ +int +isic_attach_s0163P(struct isa_device *dev) +{ + outb((dev->id_iobase) + 0x1c, 0); + DELAY(SEC_DELAY / 10); + outb((dev->id_iobase) + 0x1c, 1); + DELAY(SEC_DELAY / 10); + return(1); +} + +#else + +void +isic_attach_s0163P(struct isic_softc *sc) +{ + /* init card */ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + bus_space_write_1(t, h, 0x1c, 0); + DELAY(SEC_DELAY / 10); + bus_space_write_1(t, h, 0x1c, 1); + DELAY(SEC_DELAY / 10); + + /* setup access routines */ + + sc->clearirq = NULL; + sc->readreg = tels0163P_read_reg; + sc->writereg = tels0163P_write_reg; + + sc->readfifo = tels0163P_read_fifo; + sc->writefifo = tels0163P_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_163P; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; +} +#endif + +#endif /* ISIC > 0 */ + diff --git a/sys/i4b/layer1/i4b_usr_sti.c b/sys/i4b/layer1/i4b_usr_sti.c new file mode 100644 index 0000000..db89296 --- /dev/null +++ b/sys/i4b/layer1/i4b_usr_sti.c @@ -0,0 +1,440 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_usr_sti.c - USRobotics Sportster ISDN TA intern (Tina-pp) + * ------------------------------------------------------------- + * + * $Id: i4b_usr_sti.c,v 1.16 1998/12/05 18:05:02 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:25:34 1998] + * + *---------------------------------------------------------------------------*/ + +#if defined(__FreeBSD__) +#include "isic.h" +#include "opt_i4b.h" +#else +#define NISIC 1 +#endif +#if NISIC > 0 && defined(USR_STI) + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> + +#ifdef __FreeBSD__ +#include <machine/clock.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#endif + +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_global.h> + +/*---------------------------------------------------------------------------* + * USR Sportster TA intern special registers + *---------------------------------------------------------------------------*/ +#define USR_HSCXA_OFF 0x0000 +#define USR_HSCXB_OFF 0x4000 +#define USR_INTL_OFF 0x8000 +#define USR_ISAC_OFF 0xc000 + +#define USR_RES_BIT 0x80 /* 0 = normal, 1 = reset ISAC/HSCX */ +#define USR_INTE_BIT 0x40 /* 0 = IRQ disabled, 1 = IRQ's enabled */ +#define USR_IL_MASK 0x07 /* IRQ level config */ + +static u_char intr_no[] = { 0, 0, 0, 0, 0, 1, 0, 2, 0, 0, 3, 4, 5, 0, 6, 7 }; + +#ifdef __FreeBSD__ + +#define ADDR(reg) \ + (((reg/4) * 1024) + ((reg%4) * 2)) + +/*---------------------------------------------------------------------------* + * USRobotics read fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_read_fifo(void *buf, const void *base, size_t len) +{ + register int offset = 0; + + for(;len > 0; len--, offset++) + *((u_char *)buf + offset) = inb((int)base + ADDR(offset)); +} + +/*---------------------------------------------------------------------------* + * USRobotics write fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_fifo(void *base, const void *buf, size_t len) +{ + register int offset = 0; + + for(;len > 0; len--, offset++) + outb((int)base + ADDR(offset), *((u_char *)buf + offset)); +} + +/*---------------------------------------------------------------------------* + * USRobotics write register routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_reg(u_char *base, u_int offset, u_int v) +{ + outb((int)base + ADDR(offset), (u_char)v); +} + +/*---------------------------------------------------------------------------* + * USRobotics read register routine + *---------------------------------------------------------------------------*/ +static u_char +usrtai_read_reg(u_char *base, u_int offset) +{ + return(inb((int)base + ADDR(offset))); +} + +/*---------------------------------------------------------------------------* + * isic_probe_usrtai - probe for USR + *---------------------------------------------------------------------------*/ +int +isic_probe_usrtai(struct isa_device *dev) +{ + struct isic_softc *sc = &isic_sc[dev->id_unit]; + + /* check max unit range */ + + if(dev->id_unit >= ISIC_MAXUNIT) + { + printf("isic%d: Error, unit %d >= MAXUNIT for USR Sportster TA!\n", + dev->id_unit, dev->id_unit); + return(0); + } + sc->sc_unit = dev->id_unit; + + /* check IRQ validity */ + + if((intr_no[ffs(dev->id_irq) - 1]) == 0) + { + printf("isic%d: Error, invalid IRQ [%d] specified for USR Sportster TA!\n", + dev->id_unit, (ffs(dev->id_irq))-1); + return(0); + } + sc->sc_irq = dev->id_irq; + + /* check if memory addr specified */ + + if(dev->id_maddr) + { + printf("isic%d: Error, mem addr 0x%lx specified for USR Sportster TA!\n", + dev->id_unit, (u_long)dev->id_maddr); + return(0); + } + dev->id_msize = 0; + + /* check if we got an iobase */ + + switch(dev->id_iobase) + { + case 0x200: + case 0x208: + case 0x210: + case 0x218: + case 0x220: + case 0x228: + case 0x230: + case 0x238: + case 0x240: + case 0x248: + case 0x250: + case 0x258: + case 0x260: + case 0x268: + case 0x270: + case 0x278: + break; + + default: + printf("isic%d: Error, invalid iobase 0x%x specified for USR Sportster TA!\n", + dev->id_unit, dev->id_iobase); + return(0); + break; + } + sc->sc_port = dev->id_iobase; + + /* setup ISAC access routines */ + + sc->clearirq = NULL; + sc->readreg = usrtai_read_reg; + sc->writereg = usrtai_write_reg; + + sc->readfifo = usrtai_read_fifo; + sc->writefifo = usrtai_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_USRTA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* setup ISAC and HSCX base addr */ + + ISAC_BASE = (caddr_t)dev->id_iobase + USR_ISAC_OFF; + HSCX_A_BASE = (caddr_t)dev->id_iobase + USR_HSCXA_OFF; + HSCX_B_BASE = (caddr_t)dev->id_iobase + USR_HSCXB_OFF; + + /* + * Read HSCX A/B VSTR. Expected value for USR Sportster TA based + * boards is 0x05 in the least significant bits. + */ + + if( ((HSCX_READ(0, H_VSTR) & 0xf) != 0x5) || + ((HSCX_READ(1, H_VSTR) & 0xf) != 0x5) ) + { + printf("isic%d: HSCX VSTR test failed for USR Sportster TA\n", + dev->id_unit); + printf("isic%d: HSC0: VSTR: %#x\n", + dev->id_unit, HSCX_READ(0, H_VSTR)); + printf("isic%d: HSC1: VSTR: %#x\n", + dev->id_unit, HSCX_READ(1, H_VSTR)); + return (0); + } + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_usrtai - attach USR + *---------------------------------------------------------------------------*/ +int +isic_attach_usrtai(struct isa_device *dev) +{ + u_char irq = 0; + + /* reset the HSCX and ISAC chips */ + + outb(dev->id_iobase + USR_INTL_OFF, USR_RES_BIT); + DELAY(SEC_DELAY / 10); + + outb(dev->id_iobase + USR_INTL_OFF, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + if((irq = intr_no[ffs(dev->id_irq) - 1]) == 0) + { + printf("isic%d: Attach error, invalid IRQ [%d] specified for USR Sportster TA!\n", + dev->id_unit, ffs(dev->id_irq)-1); + return(0); + } + + /* configure and enable irq */ + + outb(dev->id_iobase + USR_INTL_OFF, irq | USR_INTE_BIT); + DELAY(SEC_DELAY / 10); + + return (1); +} + +#else /* end of FreeBSD, start NetBSD */ + +/* + * Use of sc->sc_maps: + * 0 : config register + * 1 - 16 : HSCX A registers + * 17 - 32 : HSCX B registers + * 33 - 48 : ISAC registers + */ + +#define USR_REG_OFFS(reg) ((reg % 4) * 2) +#define USR_HSCXA_MAP(reg) ((reg / 4) + 1) +#define USR_HSCXB_MAP(reg) ((reg / 4) + 17) +#define USR_ISAC_MAP(reg) ((reg / 4) + 33) + +static int map_base[] = { 33, 1, 17, 0 }; /* ISAC, HSCX A, HSCX B */ + +/*---------------------------------------------------------------------------* + * USRobotics read fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + int map, off, offset; + u_char * p = buf; + bus_space_tag_t t; + bus_space_handle_t h; + + for (offset = 0; size > 0; size--, offset++) { + map = map_base[what] + (offset / 4); + t = sc->sc_maps[map].t; + h = sc->sc_maps[map].h; + off = USR_REG_OFFS(offset); + + *p++ = bus_space_read_1(t, h, off); + } +} + +/*---------------------------------------------------------------------------* + * USRobotics write fifo routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + int map, off, offset; + const u_char * p = buf; + bus_space_tag_t t; + bus_space_handle_t h; + u_char v; + + for (offset = 0; size > 0; size--, offset++) { + map = map_base[what] + (offset / 4); + t = sc->sc_maps[map].t; + h = sc->sc_maps[map].h; + off = USR_REG_OFFS(offset); + + v = *p++; + bus_space_write_1(t, h, off, v); + } +} + +/*---------------------------------------------------------------------------* + * USRobotics write register routine + *---------------------------------------------------------------------------*/ +static void +usrtai_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + int map = map_base[what] + (offs / 4), + off = USR_REG_OFFS(offs); + bus_space_tag_t t = sc->sc_maps[map].t; + bus_space_handle_t h = sc->sc_maps[map].h; + + bus_space_write_1(t, h, off, data); +} + +/*---------------------------------------------------------------------------* + * USRobotics read register routine + *---------------------------------------------------------------------------*/ +static u_char +usrtai_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + int map = map_base[what] + (offs / 4), + off = USR_REG_OFFS(offs); + bus_space_tag_t t = sc->sc_maps[map].t; + bus_space_handle_t h = sc->sc_maps[map].h; + + return bus_space_read_1(t, h, off); +} + +/*---------------------------------------------------------------------------* + * isic_probe_usrtai - probe for USR + *---------------------------------------------------------------------------*/ +int +isic_probe_usrtai(struct isic_attach_args *ia) +{ + /* + * Read HSCX A/B VSTR. Expected value for IOM2 based + * boards is 0x05 in the least significant bits. + */ + + if(((bus_space_read_1(ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXA_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05) || + ((bus_space_read_1(ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].t, ia->ia_maps[USR_HSCXB_MAP(H_VSTR)].h, USR_REG_OFFS(H_VSTR)) & 0x0f) != 0x05)) + return 0; + + return (1); +} + +/*---------------------------------------------------------------------------* + * isic_attach_usrtai - attach USR + *---------------------------------------------------------------------------*/ +int +isic_attach_usrtai(struct isic_softc *sc) +{ + bus_space_tag_t t = sc->sc_maps[0].t; + bus_space_handle_t h = sc->sc_maps[0].h; + u_char irq = intr_no[sc->sc_irq]; + + sc->clearirq = NULL; + sc->readreg = usrtai_read_reg; + sc->writereg = usrtai_write_reg; + + sc->readfifo = usrtai_read_fifo; + sc->writefifo = usrtai_write_fifo; + + /* setup card type */ + + sc->sc_cardtyp = CARD_TYPEP_USRTA; + + /* setup IOM bus type */ + + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* reset the HSCX and ISAC chips */ + + bus_space_write_1(t, h, 0, USR_RES_BIT); + DELAY(SEC_DELAY / 10); + + bus_space_write_1(t, h, 0, 0x00); + DELAY(SEC_DELAY / 10); + + /* setup IRQ */ + + bus_space_write_1(t, h, 0, irq | USR_INTE_BIT); + DELAY(SEC_DELAY / 10); + + return (1); +} + +#endif /* __FreeBSD__ */ + +#endif /* ISIC > 0 */ diff --git a/sys/i4b/layer1/isa_isic.c b/sys/i4b/layer1/isa_isic.c new file mode 100644 index 0000000..94e4bf7 --- /dev/null +++ b/sys/i4b/layer1/isa_isic.c @@ -0,0 +1,828 @@ +/* + * Copyright (c) 1997, 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isa_isic.c - ISA bus frontend for i4b_isic driver + * -------------------------------------------------- + * + * $Id: isa_isic.c,v 1.18 1998/12/16 13:39:47 hm Exp $ + * + * last edit-date: [Mon Dec 14 10:53:16 1998] + * + * -mh original implementation + * -hm NetBSD patches from Martin + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/bus.h> + +#include <dev/isa/isavar.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> + +#if defined(__OpenBSD__) +#define __BROKEN_INDIRECT_CONFIG +#endif + +/* local functions */ +#ifdef __BROKEN_INDIRECT_CONFIG +static int isa_isic_probe __P((struct device *, void *, void *)); +#else +static int isa_isic_probe __P((struct device *, struct cfdata *, void *)); +#endif + +static void isa_isic_attach __P((struct device *, struct device *, void *)); +static int setup_io_map __P((int flags, bus_space_tag_t iot, + bus_space_tag_t memt, bus_size_t iobase, bus_size_t maddr, + int *num_mappings, struct isic_io_map *maps, int *iosize, + int *msize)); +static void args_unmap __P((int *num_mappings, struct isic_io_map *maps)); + +struct cfattach isa_isic_ca = { + sizeof(struct isic_softc), isa_isic_probe, isa_isic_attach +}; + + +/* + * Probe card + */ +static int +#ifdef __BROKEN_INDIRECT_CONFIG +isa_isic_probe(parent, match, aux) +#else +isa_isic_probe(parent, cf, aux) +#endif + struct device *parent; +#ifdef __BROKEN_INDIRECT_CONFIG + void *match; +#else + struct cfdata *cf; +#endif + void *aux; +{ +#ifdef __BROKEN_INDIRECT_CONFIG + struct cfdata *cf = ((struct device*)match)->dv_cfdata; +#endif + struct isa_attach_args *ia = aux; + bus_space_tag_t memt = ia->ia_memt, iot = ia->ia_iot; + int flags = cf->cf_flags; + struct isic_attach_args args; + int ret = 0; + + /* check irq */ + if (ia->ia_irq == IRQUNK) { + printf("isic%d: config error: no IRQ specified\n", cf->cf_unit); + return 0; + } + + /* setup MI attach args */ + bzero(&args, sizeof(args)); + args.ia_flags = flags; + + /* if card type specified setup io map for that card */ + switch(flags) + { + case FLAG_TELES_S0_8: + case FLAG_TELES_S0_16: + case FLAG_TELES_S0_163: + case FLAG_AVM_A1: + case FLAG_USR_ISDN_TA_INT: + case FLAG_ITK_IX1: + if (setup_io_map(flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &ia->ia_msize)) { + ret = 0; + goto done; + } + break; + + default: + /* no io map now, will figure card type later */ + break; + } + + /* probe card */ + switch(flags) + { +#ifdef DYNALINK + case FLAG_DYNALINK: + ret = isic_probe_Dyn(&args); + break; +#endif + +#ifdef TEL_S0_8 + case FLAG_TELES_S0_8: + ret = isic_probe_s08(&args); + break; +#endif + +#ifdef TEL_S0_16 + case FLAG_TELES_S0_16: + ret = isic_probe_s016(&args); + break; +#endif + +#ifdef TEL_S0_16_3 + case FLAG_TELES_S0_163: + ret = isic_probe_s0163(&args); + break; +#endif + +#ifdef AVM_A1 + case FLAG_AVM_A1: + ret = isic_probe_avma1(&args); + break; +#endif + +#ifdef USR_STI + case FLAG_USR_ISDN_TA_INT: + ret = isic_probe_usrtai(&args); + break; +#endif + +#ifdef ITKIX1 + case FLAG_ITK_IX1: + ret = isic_probe_itkix1(&args); + break; +#endif + + default: + /* No card type given, try to figure ... */ + if (ia->ia_iobase == IOBASEUNK) { + ret = 0; +#ifdef TEL_S0_8 + /* only Teles S0/8 will work without IO */ + args.ia_flags = FLAG_TELES_S0_8; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_s08(&args); + } +#endif /* TEL_S0_8 */ + } else if (ia->ia_maddr == MADDRUNK) { + ret = 0; +#ifdef TEL_S0_16_3 + /* no shared memory, only a 16.3 based card, + AVM A1, the usr sportster or an ITK would work */ + args.ia_flags = FLAG_TELES_S0_163; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_s0163(&args); + if (ret) + break; + } +#endif /* TEL_S0_16_3 */ +#ifdef AVM_A1 + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_AVM_A1; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_avma1(&args); + if (ret) + break; + } +#endif /* AVM_A1 */ +#ifdef USR_STI + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_USR_ISDN_TA_INT; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_usrtai(&args); + if (ret) + break; + } +#endif /* USR_STI */ + +#ifdef ITKIX1 + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_ITK_IX1; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_itkix1(&args); + if (ret) + break; + } +#endif /* ITKIX1 */ + + } else { +#ifdef TEL_S0_16_3 + /* could be anything */ + args.ia_flags = FLAG_TELES_S0_163; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_s0163(&args); + if (ret) + break; + } +#endif /* TEL_S0_16_3 */ +#ifdef TEL_S0_16 + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_TELES_S0_16; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_s016(&args); + if (ret) + break; + } +#endif /* TEL_S0_16 */ +#ifdef AVM_A1 + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_AVM_A1; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_avma1(&args); + if (ret) + break; + } +#endif /* AVM_A1 */ +#ifdef TEL_S0_8 + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + args.ia_flags = FLAG_TELES_S0_8; + if (setup_io_map(args.ia_flags, iot, memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], + &(ia->ia_iosize), &(ia->ia_msize)) == 0) + { + ret = isic_probe_s08(&args); + } +#endif /* TEL_S0_8 */ + } + break; + } + +done: + /* unmap resources */ + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + + return ret; +} + +/* + * Attach the card + */ +static void +isa_isic_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct isic_softc *sc = (void *)self; + struct isa_attach_args *ia = aux; + int flags = sc->sc_dev.dv_cfdata->cf_flags; + int ret = 0; + struct isic_attach_args args; + + /* Setup parameters */ + sc->sc_unit = sc->sc_dev.dv_unit; + sc->sc_irq = ia->ia_irq; + sc->sc_maddr = ia->ia_maddr; + sc->sc_num_mappings = 0; + sc->sc_maps = NULL; + switch(flags) + { + case FLAG_TELES_S0_8: + case FLAG_TELES_S0_16: + case FLAG_TELES_S0_163: + case FLAG_AVM_A1: + case FLAG_USR_ISDN_TA_INT: + setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &(sc->sc_num_mappings), NULL, NULL, NULL); + MALLOC_MAPS(sc); + setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL); + break; + + default: + /* No card type given, try to figure ... */ + + /* setup MI attach args */ + bzero(&args, sizeof(args)); + args.ia_flags = flags; + + /* Probe cards */ + if (ia->ia_iobase == IOBASEUNK) { + ret = 0; +#ifdef TEL_S0_8 + /* only Teles S0/8 will work without IO */ + args.ia_flags = FLAG_TELES_S0_8; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_s08(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* TEL_S0_8 */ + } else if (ia->ia_maddr == MADDRUNK) { + /* no shared memory, only a 16.3 based card, + AVM A1, the usr sportster or an ITK would work */ + ret = 0; +#ifdef TEL_S0_16_3 + args.ia_flags = FLAG_TELES_S0_163; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_s0163(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* TEL_S0_16_3 */ +#ifdef AVM_A1 + args.ia_flags = FLAG_AVM_A1; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_avma1(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* AVM_A1 */ +#ifdef USR_STI + args.ia_flags = FLAG_USR_ISDN_TA_INT; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_usrtai(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* USR_STI */ +#ifdef ITKIX1 + args.ia_flags = FLAG_ITK_IX1; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_itkix1(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* ITKIX1 */ + } else { + /* could be anything */ + ret = 0; +#ifdef TEL_S0_16_3 + args.ia_flags = FLAG_TELES_S0_163; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_s0163(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* TEL_S0_16_3 */ +#ifdef TEL_S0_16 + args.ia_flags = FLAG_TELES_S0_16; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_s016(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* TEL_S0_16 */ +#ifdef AVM_A1 + args.ia_flags = FLAG_AVM_A1; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_avma1(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* AVM_A1 */ +#ifdef TEL_S0_8 + args.ia_flags = FLAG_TELES_S0_8; + setup_io_map(args.ia_flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &args.ia_num_mappings, &args.ia_maps[0], NULL, NULL); + ret = isic_probe_s08(&args); + if (ret) + goto found; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); +#endif /* TEL_S0_8 */ + } + break; + + found: + flags = args.ia_flags; + sc->sc_num_mappings = args.ia_num_mappings; + args_unmap(&args.ia_num_mappings, &args.ia_maps[0]); + if (ret) { + MALLOC_MAPS(sc); + setup_io_map(flags, ia->ia_iot, ia->ia_memt, ia->ia_iobase, ia->ia_maddr, + &(sc->sc_num_mappings), &(sc->sc_maps[0]), NULL, NULL); + } else { + printf(": could not determine card type - not configured!\n"); + return; + } + break; + } + +#if defined(__OpenBSD__) + isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_NET, isicintr, sc, sc->sc_dev.dv_xname); + + /* MI initialization of card */ + isicattach(flags, sc); + +#else + + /* MI initialization of card */ + isicattach(flags, sc); + + /* + * Try to get a level-triggered interrupt first. If that doesn't + * work (like on NetBSD/Atari, try to establish an edge triggered + * interrupt. + */ + if (isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_LEVEL, + IPL_NET, isicintr, sc) == NULL) { + if(isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, + IPL_NET, isicintr, sc) == NULL) { + args_unmap(&(sc->sc_num_mappings), &(sc->sc_maps[0])); + free((sc)->sc_maps, M_DEVBUF); + } + else { + /* + * XXX: This is a hack that probably needs to be + * solved by setting an interrupt type in the sc + * structure. I don't feel familiar enough with the + * code to do this currently. Feel free to contact + * me about it (leo@netbsd.org). + */ + isicintr(sc); + } + } +#endif +} + +/* + * Setup card specific io mapping. Return 0 on success, + * any other value on config error. + * Be prepared to get NULL as maps array. + * Make sure to keep *num_mappings in sync with the real + * mappings already setup when returning! + */ +static int +setup_io_map(flags, iot, memt, iobase, maddr, num_mappings, maps, iosize, msize) + int flags, *num_mappings, *iosize, *msize; + bus_size_t iobase, maddr; + bus_space_tag_t iot, memt; + struct isic_io_map *maps; +{ + /* nothing mapped yet */ + *num_mappings = 0; + + /* which resources do we need? */ + switch(flags) + { + case FLAG_TELES_S0_8: + if (maddr == MADDRUNK) { + printf("isic: config error: no shared memory specified for Teles S0/8!\n"); + return 1; + } + if (iosize) *iosize = 0; /* no i/o ports */ + if (msize) *msize = 0x1000; /* shared memory size */ + + /* this card uses a single memory mapping */ + if (maps == NULL) { + *num_mappings = 1; + return 0; + } + *num_mappings = 0; + maps[0].t = memt; + maps[0].offset = 0; + maps[0].size = 0x1000; + if (bus_space_map(maps[0].t, maddr, + maps[0].size, 0, &maps[0].h)) { + return 1; + } + (*num_mappings)++; + break; + + case FLAG_TELES_S0_16: + if (iobase == IOBASEUNK) { + printf("isic: config error: no i/o address specified for Teles S0/16!\n"); + return 1; + } + if (maddr == MADDRUNK) { + printf("isic: config error: no shared memory specified for Teles S0/16!\n"); + return 1; + } + if (iosize) *iosize = 8; /* i/o ports */ + if (msize) *msize = 0x1000; /* shared memory size */ + + /* one io and one memory mapping */ + if (maps == NULL) { + *num_mappings = 2; + return 0; + } + *num_mappings = 0; + maps[0].t = iot; + maps[0].offset = 0; + maps[0].size = 8; + if (bus_space_map(maps[0].t, iobase, + maps[0].size, 0, &maps[0].h)) { + return 1; + } + (*num_mappings)++; + maps[1].t = memt; + maps[1].offset = 0; + maps[1].size = 0x1000; + if (bus_space_map(maps[1].t, maddr, + maps[1].size, 0, &maps[1].h)) { + return 1; + } + (*num_mappings)++; + break; + + case FLAG_TELES_S0_163: + if (iobase == IOBASEUNK) { + printf("isic: config error: no i/o address specified for Teles S0/16!\n"); + return 1; + } + if (iosize) *iosize = 8; /* only some i/o ports shown */ + if (msize) *msize = 0; /* no shared memory */ + + /* Four io mappings: config, isac, 2 * hscx */ + if (maps == NULL) { + *num_mappings = 4; + return 0; + } + *num_mappings = 0; + maps[0].t = iot; + maps[0].offset = 0; + maps[0].size = 8; + if (bus_space_map(maps[0].t, iobase, + maps[0].size, 0, &maps[0].h)) { + return 1; + } + (*num_mappings)++; + maps[1].t = iot; + maps[1].offset = 0; + maps[1].size = 0x40; /* XXX - ??? */ + if ((iobase - 0xd80 + 0x980) < 0 || (iobase - 0xd80 + 0x980) > 0x0ffff) + return 1; + if (bus_space_map(maps[1].t, iobase - 0xd80 + 0x980, + maps[1].size, 0, &maps[1].h)) { + return 1; + } + (*num_mappings)++; + maps[2].t = iot; + maps[2].offset = 0; + maps[2].size = 0x40; /* XXX - ??? */ + if ((iobase - 0xd80 + 0x180) < 0 || (iobase - 0xd80 + 0x180) > 0x0ffff) + return 1; + if (bus_space_map(maps[2].t, iobase - 0xd80 + 0x180, + maps[2].size, 0, &maps[2].h)) { + return 1; + } + (*num_mappings)++; + maps[3].t = iot; + maps[3].offset = 0; + maps[3].size = 0x40; /* XXX - ??? */ + if ((iobase - 0xd80 + 0x580) < 0 || (iobase - 0xd80 + 0x580) > 0x0ffff) + return 1; + if (bus_space_map(maps[3].t, iobase - 0xd80 + 0x580, + maps[3].size, 0, &maps[3].h)) { + return 1; + } + (*num_mappings)++; + break; + + case FLAG_AVM_A1: + if (iobase == IOBASEUNK) { + printf("isic: config error: no i/o address specified for AVM A1/Fritz! card!\n"); + return 1; + } + if (iosize) *iosize = 8; /* only some i/o ports shown */ + if (msize) *msize = 0; /* no shared memory */ + + /* Seven io mappings: config, isac, 2 * hscx, + isac-fifo, 2 * hscx-fifo */ + if (maps == NULL) { + *num_mappings = 7; + return 0; + } + *num_mappings = 0; + maps[0].t = iot; /* config */ + maps[0].offset = 0; + maps[0].size = 8; + if ((iobase + 0x1800) < 0 || (iobase + 0x1800) > 0x0ffff) + return 1; + if (bus_space_map(maps[0].t, iobase + 0x1800, maps[0].size, 0, &maps[0].h)) + return 1; + (*num_mappings)++; + maps[1].t = iot; /* isac */ + maps[1].offset = 0; + maps[1].size = 0x80; /* XXX - ??? */ + if ((iobase + 0x1400 - 0x20) < 0 || (iobase + 0x1400 - 0x20) > 0x0ffff) + return 1; + if (bus_space_map(maps[1].t, iobase + 0x1400 - 0x20, maps[1].size, 0, &maps[1].h)) + return 1; + (*num_mappings)++; + maps[2].t = iot; /* hscx 0 */ + maps[2].offset = 0; + maps[2].size = 0x40; /* XXX - ??? */ + if ((iobase + 0x400 - 0x20) < 0 || (iobase + 0x400 - 0x20) > 0x0ffff) + return 1; + if (bus_space_map(maps[2].t, iobase + 0x400 - 0x20, maps[2].size, 0, &maps[2].h)) + return 1; + (*num_mappings)++; + maps[3].t = iot; /* hscx 1 */ + maps[3].offset = 0; + maps[3].size = 0x40; /* XXX - ??? */ + if ((iobase + 0xc00 - 0x20) < 0 || (iobase + 0xc00 - 0x20) > 0x0ffff) + return 1; + if (bus_space_map(maps[3].t, iobase + 0xc00 - 0x20, maps[3].size, 0, &maps[3].h)) + return 1; + (*num_mappings)++; + maps[4].t = iot; /* isac-fifo */ + maps[4].offset = 0; + maps[4].size = 1; + if ((iobase + 0x1400 - 0x20 -0x3e0) < 0 || (iobase + 0x1400 - 0x20 -0x3e0) > 0x0ffff) + return 1; + if (bus_space_map(maps[4].t, iobase + 0x1400 - 0x20 -0x3e0, maps[4].size, 0, &maps[4].h)) + return 1; + (*num_mappings)++; + maps[5].t = iot; /* hscx 0 fifo */ + maps[5].offset = 0; + maps[5].size = 1; + if ((iobase + 0x400 - 0x20 -0x3e0) < 0 || (iobase + 0x400 - 0x20 -0x3e0) > 0x0ffff) + return 1; + if (bus_space_map(maps[5].t, iobase + 0x400 - 0x20 -0x3e0, maps[5].size, 0, &maps[5].h)) + return 1; + (*num_mappings)++; + maps[6].t = iot; /* hscx 1 fifo */ + maps[6].offset = 0; + maps[6].size = 1; + if ((iobase + 0xc00 - 0x20 -0x3e0) < 0 || (iobase + 0xc00 - 0x20 -0x3e0) > 0x0ffff) + return 1; + if (bus_space_map(maps[6].t, iobase + 0xc00 - 0x20 -0x3e0, maps[6].size, 0, &maps[6].h)) + return 1; + (*num_mappings)++; + break; + + case FLAG_USR_ISDN_TA_INT: + if (iobase == IOBASEUNK) { + printf("isic: config error: no I/O base specified for USR Sportster TA intern!\n"); + return 1; + } + if (iosize) *iosize = 8; /* scattered ports, only some shown */ + if (msize) *msize = 0; /* no shared memory */ + + /* 49 io mappings: 1 config and 48x8 registers */ + if (maps == NULL) { + *num_mappings = 49; + return 0; + } + *num_mappings = 0; + { + int i, num; + bus_size_t base; + + /* config at offset 0x8000 */ + base = iobase + 0x8000; + maps[0].size = 1; + maps[0].t = iot; + maps[0].offset = 0; + if (base < 0 || base > 0x0ffff) + return 1; + if (bus_space_map(iot, base, 1, 0, &maps[0].h)) { + return 1; + } + *num_mappings = num = 1; + + /* HSCX A at offset 0 */ + base = iobase; + for (i = 0; i < 16; i++) { + maps[num].size = 8; + maps[num].offset = 0; + maps[num].t = iot; + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) { + return 1; + } + *num_mappings = ++num; + } + /* HSCX B at offset 0x4000 */ + base = iobase + 0x4000; + for (i = 0; i < 16; i++) { + maps[num].size = 8; + maps[num].offset = 0; + maps[num].t = iot; + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) { + return 1; + } + *num_mappings = ++num; + } + /* ISAC at offset 0xc000 */ + base = iobase + 0xc000; + for (i = 0; i < 16; i++) { + maps[num].size = 8; + maps[num].offset = 0; + maps[num].t = iot; + if (base+i*1024 < 0 || base+i*1024+8 > 0x0ffff) + return 1; + if (bus_space_map(iot, base+i*1024, 8, 0, &maps[num].h)) { + return 1; + } + *num_mappings = ++num; + } + } + break; + + case FLAG_ITK_IX1: + if (iobase == IOBASEUNK) { + printf("isic: config error: no I/O base specified for ITK ix1 micro!\n"); + return 1; + } + if (iosize) *iosize = 4; + if (msize) *msize = 0; + if (maps == NULL) { + *num_mappings = 1; + return 0; + } + *num_mappings = 0; + maps[0].size = 4; + maps[0].t = iot; + maps[0].offset = 0; + if (bus_space_map(iot, iobase, 4, 0, &maps[0].h)) { + return 1; + } + *num_mappings = 1; + break; + + default: + printf("isic: config error: flags do not specify any known card!\n"); + return 1; + break; + } + + return 0; +} + +static void +args_unmap(num_mappings, maps) + int *num_mappings; + struct isic_io_map *maps; +{ + int i, n; + for (i = 0, n = *num_mappings; i < n; i++) + if (maps[i].size) + bus_space_unmap(maps[i].t, maps[i].h, maps[i].size); + *num_mappings = 0; +} diff --git a/sys/i4b/layer1/isapnp_isic.c b/sys/i4b/layer1/isapnp_isic.c new file mode 100644 index 0000000..9dfdf68 --- /dev/null +++ b/sys/i4b/layer1/isapnp_isic.c @@ -0,0 +1,386 @@ +/* + * Copyright (c) 1997, 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isapnp_isic.c - ISA-P&P bus frontend for i4b_isic driver + * -------------------------------------------------------- + * + * $Id: isapnp_isic.c,v 1.9 1998/12/16 13:39:47 hm Exp $ + * + * last edit-date: [Mon Dec 14 10:54:23 1998] + * + * -mh original implementation + * -hm NetBSD patches from Martin + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/bus.h> + +#include <dev/isa/isavar.h> +#include <dev/isapnp/isapnpreg.h> +#include <dev/isapnp/isapnpvar.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_global.h> + +#ifdef __BROKEN_INDIRECT_CONFIG +static int isapnp_isic_probe __P((struct device *, void *, void *)); +#else +static int isapnp_isic_probe __P((struct device *, struct cfdata *, void *)); +#endif +static void isapnp_isic_attach __P((struct device *, struct device *, void *)); + +struct cfattach isapnp_isic_ca = { + sizeof(struct isic_softc), isapnp_isic_probe, isapnp_isic_attach +}; + +typedef void (*allocmaps_func)(struct isapnp_attach_args *ipa, struct isic_softc *sc); +typedef void (*attach_func)(struct isic_softc *sc); + +/* map allocators */ +static void generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc); +static void ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc); +static void tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc); + +/* card attach functions */ +extern void isic_attach_Cs0P __P((struct isic_softc *sc)); +extern void isic_attach_Dyn __P((struct isic_softc *sc)); +extern void isic_attach_s0163P __P((struct isic_softc *sc)); +extern void isic_attach_drnngo __P((struct isic_softc *sc)); +extern void isic_attach_sws __P((struct isic_softc *sc)); +extern void isic_attach_Eqs1pi __P((struct isic_softc *sc)); + +struct isapnp_isic_card_desc { + char *devlogic; /* ISAPNP logical device ID */ + char *name; /* Name of the card */ + int card_type; /* isic card type identifier */ + allocmaps_func allocmaps; /* map allocator function */ + attach_func attach; /* card attach and init function */ +}; +static const struct isapnp_isic_card_desc +isapnp_isic_descriptions[] = +{ +#ifdef CRTX_S0_P + { "CTX0000", "Creatix ISDN S0-16 P&P", CARD_TYPEP_CS0P, + tls_pnp_mapalloc, isic_attach_Cs0P }, +#endif +#ifdef TEL_S0_16_3_P + { "TAG2110", "Teles S0/PnP", CARD_TYPEP_163P, + tls_pnp_mapalloc, isic_attach_s0163P }, +#endif +#ifdef DRN_NGO + { "SDA0150", "Dr. Neuhaus NICCY GO@", CARD_TYPEP_DRNNGO, + ngo_pnp_mapalloc, isic_attach_drnngo }, +#endif +#ifdef ELSA_QS1ISA + { "ELS0133", "Elsa QuickStep 1000 (ISA)", CARD_TYPEP_ELSAQS1ISA, + generic_pnp_mapalloc, isic_attach_Eqs1pi }, +#endif +#ifdef SEDLBAUER + { "SAG0001", "Sedlbauer WinSpeed", CARD_TYPEP_SWS, + generic_pnp_mapalloc, isic_attach_sws }, +#endif +#ifdef DYNALINK + { "ASU1688", "Dynalink IS64PH", CARD_TYPEP_DYNALINK, + generic_pnp_mapalloc, isic_attach_Dyn }, +#endif +}; +#define NUM_DESCRIPTIONS (sizeof(isapnp_isic_descriptions)/sizeof(isapnp_isic_descriptions[0])) + +/* + * Probe card + */ +static int +#ifdef __BROKEN_INDIRECT_CONFIG +isapnp_isic_probe(parent, match, aux) +#else +isapnp_isic_probe(parent, cf, aux) +#endif + struct device *parent; +#ifdef __BROKEN_INDIRECT_CONFIG + void *match; +#else + struct cfdata *cf; +#endif + void *aux; +{ + struct isapnp_attach_args *ipa = aux; + const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions; + int i; + + for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++) + if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0) + return 1; + + return 0; +} + + +/*---------------------------------------------------------------------------* + * card independend attach for ISA P&P cards + *---------------------------------------------------------------------------*/ + +/* parameter and format for message producing e.g. "isic0: " */ + +#ifdef __FreeBSD__ +#define ISIC_FMT "isic%d: " +#define ISIC_PARM dev->id_unit +#define TERMFMT " " +#else +#define ISIC_FMT "%s: " +#define ISIC_PARM sc->sc_dev.dv_xname +#define TERMFMT "\n" +#endif + +static void +isapnp_isic_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + struct isic_softc *sc = (void *)self; + struct isapnp_attach_args *ipa = aux; + const struct isapnp_isic_card_desc *desc = isapnp_isic_descriptions; + int i; + + for (i = 0; i < NUM_DESCRIPTIONS; i++, desc++) + if (strcmp(ipa->ipa_devlogic, desc->devlogic) == 0) + break; + if (i >= NUM_DESCRIPTIONS) + panic("could not identify isic PnP device"); + + /* setup parameters */ + sc->sc_cardtyp = desc->card_type; + sc->sc_unit = sc->sc_dev.dv_unit; + sc->sc_irq = ipa->ipa_irq[0].num; + desc->allocmaps(ipa, sc); + + /* announce card name */ + printf(": %s\n", desc->name); + + /* establish interrupt handler */ + isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, IST_EDGE, + IPL_NET, isicintr, sc); + + /* init card */ + isic_sc[sc->sc_unit] = sc; + desc->attach(sc); + + /* announce chip versions */ + sc->sc_isac_version = 0; + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + break; + + default: + printf(ISIC_FMT "Error, ISAC version %d unknown!\n", + ISIC_PARM, sc->sc_isac_version); + return; + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + break; + + default: + printf(ISIC_FMT "Error, HSCX version %d unknown!\n", + ISIC_PARM, sc->sc_hscx_version); + return; + break; + }; + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + /* announce chip versions */ + + if(sc->sc_isac_version >= ISAC_UNKN) + { + printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_isac_version); + sc->sc_isac_version = ISAC_UNKN; + } + else + { + printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT, + ISIC_PARM, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + } + + if(sc->sc_hscx_version >= HSCX_UNKN) + { + printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_hscx_version); + sc->sc_hscx_version = HSCX_UNKN; + } + else + { + printf(ISIC_FMT "HSCX %s" TERMFMT, + ISIC_PARM, + HSCXversion[sc->sc_hscx_version]); + } +} + +static void +generic_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc) +{ + sc->sc_num_mappings = 1; /* most cards have just one mapping */ + MALLOC_MAPS(sc); /* malloc the maps */ + sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */ + sc->sc_maps[0].h = ipa->ipa_io[0].h; + sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */ +} + +static void +ngo_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc) +{ + sc->sc_num_mappings = 2; /* one data, one address mapping */ + MALLOC_MAPS(sc); /* malloc the maps */ + sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */ + sc->sc_maps[0].h = ipa->ipa_io[0].h; + sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */ + sc->sc_maps[1].t = ipa->ipa_iot; + sc->sc_maps[1].h = ipa->ipa_io[1].h; + sc->sc_maps[1].size = 0; +} + +static void +tls_pnp_mapalloc(struct isapnp_attach_args *ipa, struct isic_softc *sc) +{ + sc->sc_num_mappings = 4; /* config, isac, 2 * hscx */ + MALLOC_MAPS(sc); /* malloc the maps */ + sc->sc_maps[0].t = ipa->ipa_iot; /* copy the access handles */ + sc->sc_maps[0].h = ipa->ipa_io[0].h; + sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */ + sc->sc_maps[1].t = ipa->ipa_iot; + sc->sc_maps[1].h = ipa->ipa_io[0].h; + sc->sc_maps[1].size = 0; + sc->sc_maps[1].offset = - 0x20; + sc->sc_maps[2].t = ipa->ipa_iot; + sc->sc_maps[2].offset = - 0x20; + sc->sc_maps[2].h = ipa->ipa_io[1].h; + sc->sc_maps[2].size = 0; + sc->sc_maps[3].t = ipa->ipa_iot; + sc->sc_maps[3].offset = 0; + sc->sc_maps[3].h = ipa->ipa_io[1].h; + sc->sc_maps[3].size = 0; +} diff --git a/sys/i4b/layer1/isic_supio.c b/sys/i4b/layer1/isic_supio.c new file mode 100644 index 0000000..6c58ad2 --- /dev/null +++ b/sys/i4b/layer1/isic_supio.c @@ -0,0 +1,374 @@ +/* + * Copyright (c) 1998 Ignatios Souvatzis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isic_supio.c - Amiga supio pseudo bus frontend for i4b_isic driver + * supports: + * - ISDN Blaster 5001/1 + * - ISDN Master 2092/64 + * But we attach to the supio, so just see "isic". + * ----------------------------------------------- + * + * $Id: isic_supio.c,v 1.5 1998/12/19 12:07:55 hm Exp $ + * + * last edit-date: [Mon Nov 16 12:29:19 1998] + * + * -is original implementation + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/bus.h> + +#include <amiga/dev/supio.h> + +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_hscx.h> +#include <i4b/layer1/i4b_isac.h> + +/*static*/ int isic_supio_match __P((struct device *, struct cfdata *, void *)); +/*static*/ void isic_supio_attach __P((struct device *, struct device *, void *)); + +/*static*/ u_int8_t aster_read_reg __P((struct isic_softc *sc, int what, + bus_size_t offs)); +/*static*/ void aster_write_reg __P((struct isic_softc *sc, int what, + bus_size_t offs, u_int8_t data)); +/*static*/ void aster_read_fifo __P((struct isic_softc *sc, int what, + void *buf, size_t size)); +/*static*/ void aster_write_fifo __P((struct isic_softc *sc, int what, + const void *data, size_t size)); + +static int supio_isicattach __P((struct isic_softc *sc)); + +struct isic_supio_softc { + struct isic_softc sc_isic; + struct isr sc_isr; + struct bus_space_tag sc_bst; +}; + +struct cfattach isic_supio_ca = { + sizeof(struct isic_supio_softc), isic_supio_match, isic_supio_attach +}; + +/* + * Probe card + */ +/*static*/ int +isic_supio_match(parent, cf, aux) + struct device *parent; + struct cfdata *cf; + void *aux; +{ + struct supio_attach_args *sap = aux; + + /* ARGSUSED */ + return (!strcmp("isic", sap->supio_name)); +} + +int isic_supio_ipl = 2; +/* + * Attach the card + */ +/*static*/ void +isic_supio_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct isic_supio_softc *ssc = (void *)self; + struct isic_softc *sc = &ssc->sc_isic; + struct supio_attach_args *sap = aux; + + bus_space_tag_t bst; + bus_space_handle_t h; + + /* setup parameters */ + sc->sc_cardtyp = CARD_TYPEP_BLMASTER; + sc->sc_num_mappings = 3; + sc->sc_unit = sc->sc_dev.dv_unit; /* XXX ??? */ + + /* create io mappings */ + MALLOC_MAPS(sc); + + bst = sap->supio_iot; + bus_space_map(bst, sap->supio_iobase, 0x400, 0, &h); + + /* ISAC */ + sc->sc_maps[0].t = bst; + sc->sc_maps[0].h = h; + sc->sc_maps[0].offset = 0x300/2; + sc->sc_maps[0].size = 0; /* foreign mapping, leave it alone */ + + /* HSCX A */ + sc->sc_maps[1].t = bst; + sc->sc_maps[1].h = h; + sc->sc_maps[1].offset = 0x100/2; + sc->sc_maps[1].size = 0; /* foreign mapping, leave it alone */ + + /* HSCX B */ + sc->sc_maps[2].t = bst; + sc->sc_maps[2].h = h; + sc->sc_maps[2].offset = 0x180/2; + sc->sc_maps[2].size = 0; /* foreign mapping, leave it alone */ + + sc->clearirq = NULL; + sc->readreg = aster_read_reg; + sc->writereg = aster_write_reg; + sc->readfifo = aster_read_fifo; + sc->writefifo = aster_write_fifo; + + /* setup card type */ + sc->sc_cardtyp = CARD_TYPEP_BLMASTER; + sc->sc_bustyp = BUS_TYPE_IOM2; + + sc->sc_ipac = 0; + sc->sc_bfifolen = HSCX_FIFO_LEN; + + /* enable RTS on HSCX A */ + aster_write_reg(sc, ISIC_WHAT_HSCXA, H_MODE, HSCX_MODE_RTS); + + /* MI initialization of card */ + + printf("\n"); + supio_isicattach(sc); + + ssc->sc_isr.isr_intr = isicintr; + ssc->sc_isr.isr_arg = sc; + ssc->sc_isr.isr_ipl = isic_supio_ipl; /* XXX */ + add_isr(&ssc->sc_isr); +} + +#if 0 +int +isic_supiointr(p) + void *p; +{ + /* XXX should test whether it is our interupt at all */ + add_sicallback((sifunc_t)isicintr, p, NULL); + return 1; +} +#endif + +/*static*/ void +aster_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what].t; + bus_space_handle_t h = sc->sc_maps[what].h; + bus_size_t o = sc->sc_maps[what].offset; + + bus_space_read_multi_1(t, h, o, buf, size); +} + +/*static*/ void +aster_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) +{ + bus_space_tag_t t = sc->sc_maps[what].t; + bus_space_handle_t h = sc->sc_maps[what].h; + bus_size_t o = sc->sc_maps[what].offset; + + bus_space_write_multi_1(t, h, o, (u_int8_t*)buf, size); +} + +/*static*/ u_int8_t +aster_read_reg(struct isic_softc *sc, int what, bus_size_t offs) +{ + bus_space_tag_t t = sc->sc_maps[what].t; + bus_space_handle_t h = sc->sc_maps[what].h; + bus_size_t o = sc->sc_maps[what].offset; + + return bus_space_read_1(t, h, o + offs); +} + +/*static*/ void +aster_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) +{ + bus_space_tag_t t = sc->sc_maps[what].t; + bus_space_handle_t h = sc->sc_maps[what].h; + bus_size_t o = sc->sc_maps[what].offset; + + bus_space_write_1(t, h, o + offs, data); +} + +/*---------------------------------------------------------------------------* + * card independend attach for pcmcia^Wsupio cards + * XXX this should be centralized! + *---------------------------------------------------------------------------*/ + +/* + * parameter and format for message producing e.g. "isic0: " + * there is no FreeBSD/Amiga, so just: + */ + +#define ISIC_FMT "%s: " +#define ISIC_PARM sc->sc_dev.dv_xname +#define TERMFMT "\n" + +int +supio_isicattach(struct isic_softc *sc) +{ + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + isic_sc[sc->sc_unit] = sc; + sc->sc_isac_version = 0; + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + break; + + default: + printf(ISIC_FMT "Error, ISAC version %d unknown!\n", + ISIC_PARM, sc->sc_isac_version); + return(0); + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + break; + + default: + printf(ISIC_FMT "Error, HSCX version %d unknown!\n", + ISIC_PARM, sc->sc_hscx_version); + return(0); + break; + }; + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + /* announce chip versions */ + + if(sc->sc_isac_version >= ISAC_UNKN) + { + printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_isac_version); + sc->sc_isac_version = ISAC_UNKN; + } + else + { + printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT, + ISIC_PARM, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + } + + if(sc->sc_hscx_version >= HSCX_UNKN) + { + printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_hscx_version); + sc->sc_hscx_version = HSCX_UNKN; + } + else + { + printf(ISIC_FMT "HSCX %s" TERMFMT, + ISIC_PARM, + HSCXversion[sc->sc_hscx_version]); + } + + return(1); +} + diff --git a/sys/i4b/layer1/pci_isic.c b/sys/i4b/layer1/pci_isic.c new file mode 100644 index 0000000..6f929e5 --- /dev/null +++ b/sys/i4b/layer1/pci_isic.c @@ -0,0 +1,327 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pci_isic.c - pcmcia bus frontend for i4b_isic driver + * ------------------------------------------------------- + * + * $Id: pci_isic.c,v 1.1 1998/12/16 13:39:47 hm Exp $ + * + * last edit-date: [Mon Nov 16 20:37:32 1998] + * + * -mh original implementation + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/bus.h> + + +#include <machine/bus.h> +#include <machine/intr.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> + +static int pci_isic_match __P((struct device *, struct cfdata *, void *)); +static void pci_isic_attach __P((struct device *, struct device *, void *)); +static const struct isic_pci_product * find_matching_card __P((struct pci_attach_args *pa)); + +extern void isic_attach_Eqs1pp __P((struct isic_softc *sc, struct pci_attach_args *pa)); +static int isic_pciattach __P((struct isic_softc *sc)); + +struct pci_isic_softc { + struct isic_softc sc_isic; /* parent class */ + + /* PCI-specific goo */ + void *sc_ih; /* interrupt handler */ +}; + +struct cfattach pci_isic_ca = { + sizeof(struct pci_isic_softc), pci_isic_match, pci_isic_attach +}; + + +static const struct isic_pci_product { + pci_vendor_id_t npp_vendor; + pci_product_id_t npp_product; + int cardtype; + int flag; + const char * name; + void (*attach)(struct isic_softc *sc, struct pci_attach_args *pa); +} isic_pci_products[] = { + { PCI_VENDOR_ELSA, 0x1000, + CARD_TYPEP_ELSAQS1PCI, FLAG_ELSA_QS1P_PCI, + "ELSA QuickStep 1000pro/PCI", + isic_attach_Eqs1pp }, + + { 0, 0, 0, 0, NULL, NULL }, +}; + +static const struct isic_pci_product * find_matching_card(pa) + struct pci_attach_args *pa; +{ + const struct isic_pci_product * pp = NULL; + + for (pp = isic_pci_products; pp->npp_vendor; pp++) + if (PCI_VENDOR(pa->pa_id) == pp->npp_vendor && + PCI_PRODUCT(pa->pa_id) == pp->npp_product) + return pp; + + return NULL; +} + +/* + * Match card + */ +static int +pci_isic_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct pci_attach_args *pa = aux; + + if (!find_matching_card(pa)) + return 0; + + return 1; +} + +/* + * Attach the card + */ +static void +pci_isic_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct pci_isic_softc *psc = (void*) self; + struct isic_softc *sc = &psc->sc_isic; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + const struct isic_pci_product * prod; + const char *intrstr; + + /* Redo probe */ + prod = find_matching_card(pa); + if (prod == NULL) return; /* oops - not found?!? */ + + sc->sc_unit = sc->sc_dev.dv_unit; + printf(": %s\n", prod->name); + + /* card initilization and sc setup */ + prod->attach(sc, pa); + + /* generic setup */ + isic_pciattach(sc); + + /* Map and establish the interrupt. */ + if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, + pa->pa_intrline, &ih)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return; + } + intrstr = pci_intr_string(pc, ih); + psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, isicintr, sc); + if (psc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); +} + +/*---------------------------------------------------------------------------* + * isic - pci device driver attach routine + *---------------------------------------------------------------------------*/ +static int +isic_pciattach(sc) + struct isic_softc *sc; +{ + int ret = 0; + + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + isic_sc[sc->sc_unit] = sc; /* XXX - hack! */ + + sc->sc_isac_version = 0; + sc->sc_hscx_version = 0; + + if(sc->sc_ipac) + { + ret = IPAC_READ(IPAC_ID); + + switch(ret) + { + case 0x01: + printf("%s: IPAC PSB2115 Version 1.1\n", sc->sc_dev.dv_xname); + break; + + default: + printf("%s: Error, IPAC version %d unknown!\n", + sc->sc_dev.dv_xname, ret); + return(0); + break; + } + } + else + { + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + printf("%s: ISAC %s (IOM-%c)\n", + sc->sc_dev.dv_xname, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + break; + + default: + printf("%s: Error, ISAC version %d unknown!\n", + sc->sc_dev.dv_xname, sc->sc_isac_version); + return(0); + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + printf("%s: HSCX %s\n", + sc->sc_dev.dv_xname, + HSCXversion[sc->sc_hscx_version]); + break; + + default: + printf("%s: Error, HSCX version %d unknown!\n", + sc->sc_dev.dv_xname, sc->sc_hscx_version); + return(0); + break; + } + } + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + +#if defined(__FreeBSD__) && __FreeBSD__ >=3 + callout_handle_init(&sc->sc_T3_callout); + callout_handle_init(&sc->sc_T4_callout); +#endif + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + return(1); +} + diff --git a/sys/i4b/layer1/pcmcia_isic.c b/sys/i4b/layer1/pcmcia_isic.c new file mode 100644 index 0000000..9d428a1 --- /dev/null +++ b/sys/i4b/layer1/pcmcia_isic.c @@ -0,0 +1,358 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcmcia_isic.c - pcmcia bus frontend for i4b_isic driver + * ------------------------------------------------------- + * + * $Id: pcmcia_isic.c,v 1.3 1998/12/05 18:05:04 hm Exp $ + * + * last edit-date: [Fri Dec 4 10:38:43 1998] + * + * -mh original implementation + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/errno.h> +#include <sys/syslog.h> +#include <sys/device.h> +#include <sys/socket.h> +#include <net/if.h> +#include <sys/systm.h> +#include <sys/malloc.h> + +#include <machine/cpu.h> +#include <machine/intr.h> +#include <machine/bus.h> + +#include <dev/pcmcia/pcmciareg.h> +#include <dev/pcmcia/pcmciavar.h> +#include <dev/pcmcia/pcmciadevs.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/layer1/i4b_l1.h> +#include <i4b/layer1/i4b_ipac.h> +#include <i4b/layer1/i4b_isac.h> +#include <i4b/layer1/i4b_hscx.h> + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer1/pcmcia_isic.h> + +static int pcmcia_isic_match __P((struct device *, struct cfdata *, void *)); +static void pcmcia_isic_attach __P((struct device *, struct device *, void *)); +static const struct isic_pcmcia_card_entry * find_matching_card __P((struct pcmcia_attach_args *pa)); +static int pcmcia_isicattach __P((struct isic_softc *sc)); + +struct cfattach pcmcia_isic_ca = { + sizeof(struct pcmcia_isic_softc), pcmcia_isic_match, pcmcia_isic_attach +}; + +struct isic_pcmcia_card_entry { + int32_t vendor; /* vendor ID */ + int32_t product; /* product ID */ + char *cis1_info[4]; /* CIS info to match */ + char *name; /* name of controller */ + int function; /* expected PCMCIA function type */ + int card_type; /* card type found */ + isic_pcmcia_attach_func attach; /* card initialization */ +}; + +static const struct isic_pcmcia_card_entry card_list[] = { + +#ifdef AVM_PCMCIA + { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, + { "AVM", "ISDN A", NULL, NULL }, + "AVM Fritz!Card", PCMCIA_FUNCTION_NETWORK, + CARD_TYPEP_PCFRITZ, isic_attach_fritzpcmcia }, +#endif + +#ifdef ELSA_ISDNMC + { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, + { "ELSA GmbH, Aachen", "MicroLink ISDN/MC ", NULL, NULL }, + "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK, + CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc }, + { PCMCIA_VENDOR_INVALID, PCMCIA_PRODUCT_INVALID, + { "ELSA AG, Aachen", "MicroLink ISDN/MC ", NULL, NULL }, + "ELSA MicroLink ISDN/MC", PCMCIA_FUNCTION_NETWORK, + CARD_TYPEP_ELSAMLIMC, isic_attach_elsaisdnmc }, +#endif + +#ifdef ELSA_MCALL + { 0x105, 0x410a, + { "ELSA", "MicroLink MC all", NULL, NULL }, + "ELSA MicroLink MCall", PCMCIA_FUNCTION_NETWORK, + CARD_TYPEP_ELSAMLMCALL, isic_attach_elsamcall }, +#endif + +}; +#define NUM_MATCH_ENTRIES (sizeof(card_list)/sizeof(card_list[0])) + +static const struct isic_pcmcia_card_entry * +find_matching_card(pa) + struct pcmcia_attach_args *pa; +{ + int i, j; + + for (i = 0; i < NUM_MATCH_ENTRIES; i++) { + if (card_list[i].vendor != PCMCIA_VENDOR_INVALID && pa->card->manufacturer != card_list[i].vendor) + continue; + if (card_list[i].product != PCMCIA_PRODUCT_INVALID && pa->card->product != card_list[i].product) + continue; + if (pa->pf->function != card_list[i].function) + continue; + for (j = 0; j < 4; j++) { + if (card_list[i].cis1_info[j] == NULL) + continue; /* wildcard */ + if (pa->card->cis1_info[j] == NULL) + break; /* not available */ + if (strcmp(pa->card->cis1_info[j], card_list[i].cis1_info[j]) != 0) + break; /* mismatch */ + } + if (j >= 4) + break; + } + if (i >= NUM_MATCH_ENTRIES) + return NULL; + + return &card_list[i]; +} + +/* + * Match card + */ +static int +pcmcia_isic_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct pcmcia_attach_args *pa = aux; + + if (!find_matching_card(pa)) + return 0; + + return 1; +} + +/* + * Attach the card + */ +static void +pcmcia_isic_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct pcmcia_isic_softc *psc = (void*) self; + struct isic_softc *sc = &psc->sc_isic; + struct pcmcia_attach_args *pa = aux; + struct pcmcia_config_entry *cfe; + const struct isic_pcmcia_card_entry * cde; + + /* Which card is it? */ + cde = find_matching_card(pa); + if (cde == NULL) return; /* oops - not found?!? */ + + psc->sc_pf = pa->pf; + cfe = pa->pf->cfe_head.sqh_first; + + /* Enable the card */ + pcmcia_function_init(pa->pf, cfe); + pcmcia_function_enable(pa->pf); + + if (!cde->attach(psc, cfe, pa)) + return; /* Ooops ? */ + + sc->sc_unit = sc->sc_dev.dv_unit; + + /* Announce card name */ + printf(": %s\n", cde->name); + + /* MI initilization */ + pcmcia_isicattach(sc); + + /* setup interrupt */ + psc->sc_ih = pcmcia_intr_establish(pa->pf, IPL_NET, isicintr, sc); +} + +/*---------------------------------------------------------------------------* + * card independend attach for pcmicia cards + *---------------------------------------------------------------------------*/ + +/* parameter and format for message producing e.g. "isic0: " */ + +#ifdef __FreeBSD__ +#define ISIC_FMT "isic%d: " +#define ISIC_PARM dev->id_unit +#define TERMFMT " " +#else +#define ISIC_FMT "%s: " +#define ISIC_PARM sc->sc_dev.dv_xname +#define TERMFMT "\n" +#endif + +int +pcmcia_isicattach(struct isic_softc *sc) +{ + static char *ISACversion[] = { + "2085 Version A1/A2 or 2086/2186 Version 1.1", + "2085 Version B1", + "2085 Version B2", + "2085 Version V2.3 (B3)", + "Unknown Version" + }; + + static char *HSCXversion[] = { + "82525 Version A1", + "Unknown (0x01)", + "82525 Version A2", + "Unknown (0x03)", + "82525 Version A3", + "82525 or 21525 Version 2.1", + "Unknown Version" + }; + + isic_sc[sc->sc_unit] = sc; + sc->sc_isac_version = 0; + sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; + + switch(sc->sc_isac_version) + { + case ISAC_VA: + case ISAC_VB1: + case ISAC_VB2: + case ISAC_VB3: + break; + + default: + printf(ISIC_FMT "Error, ISAC version %d unknown!\n", + ISIC_PARM, sc->sc_isac_version); + return(0); + break; + } + + sc->sc_hscx_version = HSCX_READ(0, H_VSTR) & 0xf; + + switch(sc->sc_hscx_version) + { + case HSCX_VA1: + case HSCX_VA2: + case HSCX_VA3: + case HSCX_V21: + break; + + default: + printf(ISIC_FMT "Error, HSCX version %d unknown!\n", + ISIC_PARM, sc->sc_hscx_version); + return(0); + break; + }; + + /* ISAC setup */ + + isic_isac_init(sc); + + /* HSCX setup */ + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_A, BPROT_NONE, 0); + + isic_bchannel_setup(sc->sc_unit, HSCX_CH_B, BPROT_NONE, 0); + + /* setup linktab */ + + isic_init_linktab(sc); + + /* set trace level */ + + sc->sc_trace = TRACE_OFF; + + sc->sc_state = ISAC_IDLE; + + sc->sc_ibuf = NULL; + sc->sc_ib = NULL; + sc->sc_ilen = 0; + + sc->sc_obuf = NULL; + sc->sc_op = NULL; + sc->sc_ol = 0; + sc->sc_freeflag = 0; + + sc->sc_obuf2 = NULL; + sc->sc_freeflag2 = 0; + + /* init higher protocol layers */ + + MPH_Status_Ind(sc->sc_unit, STI_ATTACH, sc->sc_cardtyp); + + /* announce chip versions */ + + if(sc->sc_isac_version >= ISAC_UNKN) + { + printf(ISIC_FMT "ISAC Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_isac_version); + sc->sc_isac_version = ISAC_UNKN; + } + else + { + printf(ISIC_FMT "ISAC %s (IOM-%c)" TERMFMT, + ISIC_PARM, + ISACversion[sc->sc_isac_version], + sc->sc_bustyp == BUS_TYPE_IOM1 ? '1' : '2'); + } + + if(sc->sc_hscx_version >= HSCX_UNKN) + { + printf(ISIC_FMT "HSCX Version UNKNOWN (VN=0x%x)" TERMFMT, + ISIC_PARM, + sc->sc_hscx_version); + sc->sc_hscx_version = HSCX_UNKN; + } + else + { + printf(ISIC_FMT "HSCX %s" TERMFMT, + ISIC_PARM, + HSCXversion[sc->sc_hscx_version]); + } + + return(1); +} + diff --git a/sys/i4b/layer1/pcmcia_isic.h b/sys/i4b/layer1/pcmcia_isic.h new file mode 100644 index 0000000..73f52d6 --- /dev/null +++ b/sys/i4b/layer1/pcmcia_isic.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcmcia_isic.h - common definitions for pcmcia isic cards + * -------------------------------------------------------- + * + * $Id: pcmcia_isic.h,v 1.1 1998/12/02 06:44:30 hm Exp $ + * + * last edit-date: [Mon Nov 30 21:19:14 1998] + * + * -mh original implementation + * + *---------------------------------------------------------------------------*/ + +struct pcmcia_isic_softc { + struct isic_softc sc_isic; /* parent class */ + + /* PCMCIA-specific goo */ + struct pcmcia_io_handle sc_pcioh; /* PCMCIA i/o space info */ + int sc_io_window; /* our i/o window */ + struct pcmcia_function *sc_pf; /* our PCMCIA function */ + void *sc_ih; /* interrupt handler */ +}; + +typedef int (*isic_pcmcia_attach_func)(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa); + +extern int isic_attach_fritzpcmcia(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa); +extern int isic_attach_elsaisdnmc(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa); +extern int isic_attach_elsamcall(struct pcmcia_isic_softc *sc, struct pcmcia_config_entry *cfe, struct pcmcia_attach_args *pa); + + diff --git a/sys/i4b/layer2/i4b_iframe.c b/sys/i4b/layer2/i4b_iframe.c new file mode 100644 index 0000000..c5e38d8 --- /dev/null +++ b/sys/i4b/layer2/i4b_iframe.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_iframe.c - i frame handling routines + * ------------------------------------------ + * + * $Id: i4b_iframe.c,v 1.15 1998/12/05 18:05:06 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:26:16 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_trace.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * process i frame + * implements the routine "I COMMAND" Q.921 03/93 pp 77 + *---------------------------------------------------------------------------*/ +void +i4b_rxd_i_frame(int unit, struct mbuf *m) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + u_char *ptr = m->m_data; + int nr; + int ns; + int p; + int x; + + if(!((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))) + { + i4b_Dfreembuf(m); + return; + } + + if((l2sc->Q921_state != ST_MULTIFR) && (l2sc->Q921_state != ST_TIMREC)) + { + i4b_Dfreembuf(m); + DBGL2(L2_I_ERR, "i4b_rxd_i_frame", ("ERROR, state != (MF || TR)!\n")); + return; + } + + x = SPLI4B(); + + nr = GETINR(*(ptr + OFF_INR)); + ns = GETINS(*(ptr + OFF_INS)); + p = GETIP(*(ptr + OFF_INR)); + + i4b_rxd_ack(l2sc, nr); /* last packet ack */ + + if(l2sc->own_busy) /* own receiver busy ? */ + { + i4b_Dfreembuf(m); /* yes, discard information */ + + if(p == 1) /* P bit == 1 ? */ + { + i4b_tx_rnr_response(l2sc, p); /* yes, tx RNR */ + l2sc->ack_pend = 0; /* clear ACK pending */ + } + } + else /* own receiver ready */ + { + if(ns == l2sc->vr) /* expected sequence number ? */ + { + M128INC(l2sc->vr); /* yes, update */ + + l2sc->rej_excpt = 0; /* clr reject exception */ + + m_adj(m, I_HDR_LEN); /* strip i frame header */ + + l2sc->iframe_sent = 0; /* reset i acked already */ + + DL_Data_Ind(l2sc->unit, m); /* pass data up */ + + if(!l2sc->iframe_sent) + { + i4b_tx_rr_response(l2sc, p); /* yes, tx RR */ + l2sc->ack_pend = 0; /* clr ACK pending */ + } + } + else /* ERROR, sequence number NOT expected */ + { + i4b_Dfreembuf(m); /* discard information */ + + if(l2sc->rej_excpt == 1) /* already exception ? */ + { + if(p == 1) /* immediate response ? */ + { + i4b_tx_rr_response(l2sc, p); /* yes, tx RR */ + l2sc->ack_pend = 0; /* clr ack pend */ + } + } + else /* not in exception cond */ + { + l2sc->rej_excpt = 1; /* set exception */ + i4b_tx_rej_response(l2sc, p); /* tx REJ */ + l2sc->ack_pend = 0; /* clr ack pending */ + } + } + } + + /* sequence number ranges as expected ? */ + + if(i4b_l2_nr_ok(nr, l2sc->va, l2sc->vs)) + { + if(l2sc->Q921_state == ST_TIMREC) + { + l2sc->va = nr; + splx(x); + return; + } + + if(l2sc->peer_busy) /* yes, other side busy ? */ + { + l2sc->va = nr; /* yes, update ack count */ + } + else /* other side ready */ + { + if(nr == l2sc->vs) /* count expected ? */ + { + l2sc->va = nr; /* update ack */ + i4b_T200_stop(l2sc); + i4b_T203_restart(l2sc); + } + else + { + if(nr != l2sc->va) + { + l2sc->va = nr; + i4b_T200_restart(l2sc); + } + } + } + } + else + { + i4b_nr_error_recovery(l2sc); /* sequence error */ + l2sc->Q921_state = ST_AW_EST; + } + splx(x); +} + +/*---------------------------------------------------------------------------* + * internal I FRAME QUEUED UP routine (Q.921 03/93 p 61) + *---------------------------------------------------------------------------*/ +void +i4b_i_frame_queued_up(l2_softc_t *l2sc) +{ + int x; + struct mbuf *m; + u_char *ptr; + + x = SPLI4B(); + + if(l2sc->peer_busy) + { + DBGL2(L2_I_MSG, "i4b_i_frame_queued_up", ("peer busy!\n")); + i4b_print_l2var(l2sc); + splx(x); + return; + } + + if(l2sc->vs == ((l2sc->va + MAX_K_VALUE) & 127)) + { + DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("V(S) == ((V(A) + k) & 127)!\n")); + DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("state = %s\n", i4b_print_l2state(l2sc))); + i4b_print_l2var(l2sc); + splx(x); + return; + } + + IF_DEQUEUE(&l2sc->i_queue, m); /* fetch next frame to tx */ + + if(!m) + { + DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("ERROR, mbuf NULL after IF_DEQUEUE\n")); + splx(x); + return; + } + + ptr = m->m_data; + + PUTSAPI(SAPI_CCP, CR_CMD_TO_NT, *(ptr + OFF_SAPI)); + PUTTEI(l2sc->tei, *(ptr + OFF_TEI)); + + *(ptr + OFF_INS) = (l2sc->vs << 1) & 0xfe; /* bit 0 = 0 */ + *(ptr + OFF_INR) = (l2sc->vr << 1) & 0xfe; /* P bit = 0 */ + + PH_Data_Req(l2sc->unit, m, MBUF_DONTFREE); /* free'd when ack'd ! */ + + l2sc->iframe_sent = 1; /* in case we ack an I frame with another I frame */ + + if(l2sc->ua_num != UA_EMPTY) /* failsafe */ + { + DBGL2(L2_I_ERR, "i4b_i_frame_queued_up", ("ERROR, l2sc->ua_num: %d != UA_EMPTY\n", l2sc->ua_num)); + i4b_print_l2var(l2sc); + i4b_Dfreembuf(l2sc->ua_frame); + } + + l2sc->ua_frame = m; /* save unacked frame */ + l2sc->ua_num = l2sc->vs; /* save frame number */ + + M128INC(l2sc->vs); + + l2sc->ack_pend = 0; + + splx(x); + + if(l2sc->T200 == TIMER_IDLE) + { + i4b_T203_stop(l2sc); + i4b_T200_start(l2sc); + } +} + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_l2.c b/sys/i4b/layer2/i4b_l2.c new file mode 100644 index 0000000..5cdc1c7 --- /dev/null +++ b/sys/i4b/layer2/i4b_l2.c @@ -0,0 +1,390 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2.c - ISDN layer 2 (Q.921) + * ------------------------------- + * + * $Id: i4b_l2.c,v 1.23 1998/12/05 18:05:08 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:27:00 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +int i4b_dl_establish_ind(int); +int i4b_dl_establish_cnf(int); +int i4b_dl_release_ind(int); +int i4b_dl_release_cnf(int); +int i4b_dl_data_ind(int, struct mbuf *); +int i4b_dl_unit_data_ind(int, struct mbuf *); + +static int i4b_mdl_command_req(int, int, int); + +/* from layer 2 */ + +extern int i4b_mdl_attach_ind(int, int); +extern int i4b_mdl_status_ind(int, int, int); + +/* this layers debug level */ + +unsigned int i4b_l2_debug = L2_DEBUG_DEFAULT; + +struct i4b_l2l3_func i4b_l2l3_func = { + + /* Layer 2 --> Layer 3 */ + + (int (*)(int)) i4b_dl_establish_ind, + (int (*)(int)) i4b_dl_establish_cnf, + (int (*)(int)) i4b_dl_release_ind, + (int (*)(int)) i4b_dl_release_cnf, + (int (*)(int, struct mbuf *)) i4b_dl_data_ind, + (int (*)(int, struct mbuf *)) i4b_dl_unit_data_ind, + + /* Layer 3 --> Layer 2 */ + + (int (*)(int)) i4b_dl_establish_req, + (int (*)(int)) i4b_dl_release_req, + (int (*)(int, struct mbuf *)) i4b_dl_data_req, + (int (*)(int, struct mbuf *)) i4b_dl_unit_data_req, + + /* Layer 2 --> Layer 3 management */ + + (int (*)(int, int, int)) i4b_mdl_status_ind, + + /* Layer 3 --> Layer 2 management */ + + (int (*)(int, int, int)) i4b_mdl_command_req +}; + +/*---------------------------------------------------------------------------* + * DL_ESTABLISH_REQ from layer 3 + *---------------------------------------------------------------------------*/ +int i4b_dl_establish_req(int unit) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + + DBGL2(L2_PRIM, "DL-ESTABLISH-REQ", ("unit %d\n",unit)); + i4b_l1_activate(l2sc); + i4b_next_l2state(l2sc, EV_DLESTRQ); + return(0); +} + +/*---------------------------------------------------------------------------* + * DL_RELEASE_REQ from layer 3 + *---------------------------------------------------------------------------*/ +int i4b_dl_release_req(int unit) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + + DBGL2(L2_PRIM, "DL-RELEASE-REQ", ("unit %d\n",unit)); + i4b_next_l2state(l2sc, EV_DLRELRQ); + return(0); +} + +/*---------------------------------------------------------------------------* + * DL UNIT DATA REQUEST from Layer 3 + *---------------------------------------------------------------------------*/ +int i4b_dl_unit_data_req(int unit, struct mbuf *m) +{ +#ifdef NOTDEF + DBGL2(L2_PRIM, "DL-UNIT-DATA-REQ", ("unit %d\n",unit)); +#endif + return(0); +} + +/*---------------------------------------------------------------------------* + * DL DATA REQUEST from Layer 3 + *---------------------------------------------------------------------------*/ +int i4b_dl_data_req(int unit, struct mbuf *m) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + int x; +#ifdef NOTDEF + DBGL2(L2_PRIM, "DL-DATA-REQ", ("unit %d\n",unit)); +#endif + switch(l2sc->Q921_state) + { + case ST_AW_EST: + case ST_MULTIFR: + case ST_TIMREC: + + if(IF_QFULL(&l2sc->i_queue)) + { + DBGL2(L2_ERROR, "i4b_dl_data_req", ("i_queue full!!\n")); + i4b_Dfreembuf(m); + } + else + { + x = splimp(); + IF_ENQUEUE(&l2sc->i_queue, m); + splx(x); + i4b_i_frame_queued_up(l2sc); + } + break; + + default: + DBGL2(L2_ERROR, "i4b_dl_data_req", ("unit %d ERROR in state [%s], freeing mbuf\n", unit, i4b_print_l2state(l2sc))); + i4b_Dfreembuf(m); + break; + } + return(0); +} + +/*---------------------------------------------------------------------------* + * i4b_ph_activate_ind - link activation indication from layer 1 + *---------------------------------------------------------------------------*/ +int +i4b_ph_activate_ind(int unit) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + + DBGL1(L1_PRIM, "PH-ACTIVATE-IND", ("unit %d\n",unit)); + l2sc->ph_active = PH_ACTIVE; + return(0); +} + +/*---------------------------------------------------------------------------* + * i4b_ph_deactivate_ind - link deactivation indication from layer 1 + *---------------------------------------------------------------------------*/ +int +i4b_ph_deactivate_ind(int unit) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + + DBGL1(L1_PRIM, "PH-DEACTIVATE-IND", ("unit %d\n",unit)); + l2sc->ph_active = PH_INACTIVE; + return(0); +} + + +/*---------------------------------------------------------------------------* + * i4b_l2_unit_init - place layer 2 unit into known state + *---------------------------------------------------------------------------*/ +static void +i4b_l2_unit_init(int unit) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + + l2sc->Q921_state = ST_TEI_UNAS; + l2sc->tei_valid = TEI_INVALID; + l2sc->vr = 0; + l2sc->vs = 0; + l2sc->va = 0; + l2sc->ack_pend = 0; + l2sc->rej_excpt = 0; + l2sc->peer_busy = 0; + l2sc->own_busy = 0; + l2sc->l3initiated = 0; + + l2sc->rxd_CR = 0; + l2sc->rxd_PF = 0; + l2sc->rxd_NR = 0; + l2sc->RC = 0; + l2sc->iframe_sent = 0; + + l2sc->postfsmfunc = NULL; + + if(l2sc->ua_num != UA_EMPTY) + { + i4b_Dfreembuf(l2sc->ua_frame); + l2sc->ua_num = UA_EMPTY; + l2sc->ua_frame = NULL; + } + + i4b_T200_stop(l2sc); + i4b_T202_stop(l2sc); + i4b_T203_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * i4b_mph_status_ind - status indication upward + *---------------------------------------------------------------------------*/ +int +i4b_mph_status_ind(int unit, int status, int parm) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + int sendup = 1; + + int x = SPLI4B(); + + DBGL1(L1_PRIM, "MPH-STATUS-IND", ("unit %d, status=%d, parm=%d\n", unit, status, parm)); + + switch(status) + { + case STI_ATTACH: + l2sc->unit = unit; + l2sc->i_queue.ifq_maxlen = IQUEUE_MAXLEN; + l2sc->ua_frame = NULL; + i4b_l2_unit_init(unit); + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + /* initialize the callout handles for timeout routines */ + callout_handle_init(&l2sc->T200_callout); + callout_handle_init(&l2sc->T202_callout); + callout_handle_init(&l2sc->T203_callout); +#endif + break; + + case STI_L1STAT: /* state of layer 1 */ + break; + + case STI_PDEACT: /* Timer 4 expired */ + if((l2sc->Q921_state >= ST_AW_EST) && + (l2sc->Q921_state <= ST_TIMREC)) + { + DBGL2(L2_ERROR, "i4b_mph_status_ind", ("unit %d, persistent deactivation!\n", unit)); + i4b_l2_unit_init(unit); + } + else + { + sendup = 0; + } + break; + + case STI_NOL1ACC: + i4b_l2_unit_init(unit); + DBGL2(L2_ERROR, "i4b_mph_status_ind", ("unit %d, cannot access S0 bus!\n", unit)); + break; + + default: + DBGL2(L2_ERROR, "i4b_mph_status_ind", ("ERROR, unit %d, unknown status message!\n", unit)); + break; + } + + if(sendup) + MDL_Status_Ind(unit, status, parm); /* send up to layer 3 */ + + splx(x); + + return(0); +} + +/*---------------------------------------------------------------------------* + * MDL_COMMAND_REQ from layer 3 + *---------------------------------------------------------------------------*/ +int i4b_mdl_command_req(int unit, int command, int parm) +{ + DBGL2(L2_PRIM, "MDL-COMMAND-REQ", ("unit %d, command=%d, parm=%d\n", unit, command, parm)); + + switch(command) + { + case CMR_DOPEN: + i4b_l2_unit_init(unit); + break; + } + + MPH_Command_Req(unit, command, parm); + + return(0); +} + +/*---------------------------------------------------------------------------* + * i4b_ph_data_ind - process a rx'd frame got from layer 1 + *---------------------------------------------------------------------------*/ +int +i4b_ph_data_ind(int unit, struct mbuf *m) +{ +#ifdef NOTDEF + DBGL1(L1_PRIM, "PH-DATA-IND", ("unit %d\n", unit)); +#endif + u_char *ptr = m->m_data; + + if ( (*(ptr + OFF_CNTL) & 0x01) == 0 ) + { + if(m->m_len < 4) /* 6 oct - 2 chksum oct */ + { + DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, I-frame < 6 octetts!\n")); + i4b_Dfreembuf(m); + return(0); + } + i4b_rxd_i_frame(unit, m); + } + else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x01 ) + { + if(m->m_len < 4) /* 6 oct - 2 chksum oct */ + { + DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, S-frame < 6 octetts!\n")); + i4b_Dfreembuf(m); + return(0); + } + i4b_rxd_s_frame(unit, m); + } + else if ( (*(ptr + OFF_CNTL) & 0x03) == 0x03 ) + { + if(m->m_len < 3) /* 5 oct - 2 chksum oct */ + { + DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, U-frame < 5 octetts!\n")); + i4b_Dfreembuf(m); + return(0); + } + i4b_rxd_u_frame(unit, m); + } + else + { + DBGL2(L2_ERROR, "i4b_ph_data_ind", ("ERROR, bad frame rx'd - ")); + i4b_print_frame(m->m_len, m->m_data); + i4b_Dfreembuf(m); + } + return(0); +} + +#endif /* NI4BQ921 > 0 */ + diff --git a/sys/i4b/layer2/i4b_l2.h b/sys/i4b/layer2/i4b_l2.h new file mode 100644 index 0000000..ab1dfd7 --- /dev/null +++ b/sys/i4b/layer2/i4b_l2.h @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2.h - ISDN layer 2 (Q.921) definitions + * --------------------------------------------- + * + * $Id: i4b_l2.h,v 1.14 1998/12/05 18:05:09 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:27:13 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L2_H_ +#define _I4B_L2_H_ + +typedef struct { + int unit; /* unit number this entry is for */ + + int Q921_state; /* state according to Q.921 */ + + u_char last_ril; /* last reference number from TEI management */ + u_char last_rih; + + int tei_valid; /* tei is valid flag */ +#define TEI_INVALID 0 +#define TEI_VALID 1 + int tei; /* tei, if tei flag valid */ + + int ph_active; /* Layer 1 active flag */ +#define PH_INACTIVE 0 /* layer 1 inactive */ +#define PH_ACTIVEPEND 1 /* already tried to activate */ +#define PH_ACTIVE 2 /* layer 1 active */ + + int T200; /* Multiframe timeout timer */ + int T201; /* min time between TEI ID check */ + int T202; /* min time between TEI ID Req messages */ + int N202; /* TEI ID Req tx counter */ + void(*T202func)(void *);/* function to be called when T202 expires */ + int T203; /* max line idle time */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + struct callout_handle T200_callout; + struct callout_handle T202_callout; + struct callout_handle T203_callout; +#endif + + int vr; /* receive sequence frame counter */ + int vs; /* transmit sequence frame counter */ + int va; /* acknowledge sequence frame counter */ + + int ack_pend; /* acknowledge pending */ + int rej_excpt; /* reject exception */ + int peer_busy; /* peer receiver busy */ + int own_busy; /* own receiver busy */ + int l3initiated; /* layer 3 initiated */ + + struct ifqueue i_queue; /* queue of outgoing i frames */ +#define IQUEUE_MAXLEN 20 + + /* this implementation only supports a k-value of 1 !!! */ + struct mbuf *ua_frame; /* last unacked frame */ + int ua_num; /* last unacked frame number */ +#define UA_EMPTY (-1) /* ua_frame is unused */ + + int rxd_CR; /* received Command Response bit */ + int rxd_PF; /* received Poll/Final bit */ + int rxd_NR; /* received N(R) field */ + int RC; /* Retry Counter */ + + int iframe_sent; /* check if i frame acked by another i frame */ + + int (*postfsmfunc)(int);/* function to be called at fsm exit */ + int postfsmarg; /* argument for above function */ +} l2_softc_t; + +extern l2_softc_t l2_softc[]; + +/* Q.912 system parameters (Q.921 03/93 pp 43) */ + +#define MAX_K_VALUE 1 /* BRI - # of outstanding frames */ + +#define N200 3 /* max no of retransmissions */ +#define N201DEF 260 /* max no of octetts in information field */ +#define N202DEF 3 /* max no of TEI ID Request message transmissions */ + +#define T200DEF (hz*1) /* default T200 timer value = 1 second */ +#define T201DEF T200DEF /* default T201 timer value = T200DEF */ +#define T202DEF (hz*2) /* default T202 timer value = 2 seconds */ +#define T203DEF (hz*10) /* default T203 timer value = 10 seconds*/ + +/* modulo 128 operations */ + +#define M128INC(v) (v)++; \ + if((v)>127) \ + { \ + v = 0; \ + } + +#define M128DEC(v) (v)--; \ + if((v)<0) \ + { \ + v = 127;\ + } + +/* P-bit values */ + +typedef enum { + P0, + P1 +} pbit_t; + +/* F-bit values */ + +typedef enum { + F0, + F1 +} fbit_t; + +/* CR-bit values to NT */ + +typedef enum { + CR_CMD_TO_NT, + CR_RSP_TO_NT +} crbit_to_nt_t; + +/* CR-bit values from NT */ + +typedef enum { + CR_RSP_FROM_NT, + CR_CMD_FROM_NT +} crbit_from_nt_t; + +/* address field - octett 2 */ + +#define OFF_SAPI 0 /* SAPI offset, HDLC flag is eaten by L1 */ +#define SAPI_CCP 0 /* SAPI = 0 - call control procedures */ +#define SAPI_X25 16 /* SAPI = 16 - X.25 packet procedures */ +#define SAPI_L2M 63 /* SAPI = 63 - Layer 2 management procedures */ + +/* extract and insert macros for SAPI octett */ + +#define GETSAPI(octett) (((octett) >> 2) & 0x3f) +#define PUTSAPI(sapi,cr,octett) ((octett) = (((sapi << 2) & 0xfc) | ((cr & 0x01) << 1))) +#define GETCR(octett) (((octett) >> 1) & 0x01) +#define GETEA(octett) ((octett) & 0x01) + +/* address field - octett 3 */ + +#define OFF_TEI 1 /* TEI offset */ +#define GETTEI(octett) (((octett) >> 1) & 0x7f) +#define PUTTEI(tei, octett) ((octett) = ((((tei) << 1) & 0xfe)) | 0x01) +#define GROUP_TEI 127 /* broadcast TEI for LME */ + +/* control field - octett 4 */ + +#define OFF_CNTL 2 /* 1st byte of control field */ + +/* S frames */ + +#define S_FRAME_LEN 4 /* lenght of a U-frame */ +#define OFF_SRCR 2 /* 1st byte of control field, */ + /* R-commands and R-responses */ +#define OFF_SNR 3 /* 2nd byte of control field, N(R) and PF */ +#define SPFBIT 0x01 /* poll/final bit mask */ +#define SPBITSET SPFBIT +#define SFBITSET SPFBIT +#define GETSNR(octett) (((octett) >> 1) & 0x7f) +#define GETSPF(octett) ((octett) & SPFBIT) +#define RR 0x01 /* RR and bit 0 set */ +#define RNR 0x05 /* RNR and bit 0 set */ +#define REJ 0x09 /* REJ and bit 0 set */ + +/* U frames */ + +#define UI_HDR_LEN 3 /* length of UI header in front of L3 frame */ +#define U_FRAME_LEN 3 /* lenght of a U-frame */ +#define UPFBIT 0x10 /* poll/final bit mask */ +#define UPBITSET UPFBIT +#define UFBITSET UPFBIT +#define GETUPF(octett) (((octett) >> 4) & 0x01) + +/* commands/responses with pf bit set to 0 */ + +#define SABME 0x6f +#define DM 0x0f +#define UI 0x03 +#define DISC 0x43 +#define UA 0x63 +#define FRMR 0x87 +#define XID 0xaf + +/* control field - octett 3 */ + +#define OFF_MEI 3 /* 2nd byte of control field */ + +/* control field - octett 4,5 */ + +#define OFF_RIL 4 /* Ri low byte */ +#define OFF_RIH 5 /* Ri high byte */ + +/* control field - octett 6 */ + +#define OFF_MT 6 /* Message Type */ +#define OFF_AI 7 /* Action Indicator */ +#define GET_TEIFROMAI(octett) (((octett) >> 1) & 0x7f) + +/* I frame */ + +#define I_HDR_LEN 4 /* length of I header in front of L3 frame */ +#define OFF_INS 2 /* transmit sequence number */ +#define OFF_INR 3 /* receive sequence number */ +#define IPFBIT 0x01 /* poll/final bit mask */ +#define IPBITSET 0x01 +#define GETINR(octett) (((octett) >> 1) & 0x7f) +#define GETINS(octett) (((octett) >> 1) & 0x7f) +#define GETIP(octett) ((octett) & IPFBIT) + +/* structure of a TEI management frame */ + +#define TEI_MGMT_FRM_LEN 8 /* frame length */ +#define TEIM_SAPIO 0x00 /* SAPI, CR, EA */ +#define TEIM_TEIO 0x01 /* TEI, EA */ +#define TEIM_UIO 0x02 /* frame type = UI = 0x03 */ +#define TEIM_MEIO 0x03 /* management entity id = 0x0f */ +#define MEI 0x0f +#define TEIM_RILO 0x04 /* reference number, low */ +#define TEIM_RIHO 0x05 /* reference number, high */ +#define TEIM_MTO 0x06 /* message type */ +#define MT_ID_REQEST 0x01 +#define MT_ID_ASSIGN 0x02 +#define MT_ID_DENY 0x03 +#define MT_ID_CHK_REQ 0x04 +#define MT_ID_CHK_RSP 0x05 +#define MT_ID_REMOVE 0x06 +#define MT_ID_VERIFY 0x07 +#define TEIM_AIO 0x07 /* action indicator */ + +/* i4b_mdl_error_ind codes */ + +enum MDL_ERROR_CODES { + MDL_ERR_A, + MDL_ERR_B, + MDL_ERR_C, + MDL_ERR_D, + MDL_ERR_E, + MDL_ERR_F, + MDL_ERR_G, + MDL_ERR_H, + MDL_ERR_I, + MDL_ERR_J, + MDL_ERR_K, + MDL_ERR_L, + MDL_ERR_M, + MDL_ERR_N, + MDL_ERR_O, + MDL_ERR_MAX +}; + +/* forward decl */ + +extern void i4b_acknowledge_pending ( l2_softc_t *l2sc ); +extern struct mbuf * i4b_build_s_frame ( l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type ); +extern struct mbuf * i4b_build_u_frame ( l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type ); +extern void i4b_clear_exception_conditions ( l2_softc_t *l2sc ); +extern int i4b_dl_data_req ( int unit, struct mbuf *m ); +extern int i4b_dl_establish_req ( int unit ); +extern int i4b_dl_release_req ( int unit ); +extern int i4b_dl_unit_data_req ( int unit, struct mbuf *m ); +extern void i4b_enquiry_response ( l2_softc_t *l2sc ); +extern void i4b_establish_data_link ( l2_softc_t *l2sc ); +extern void i4b_invoke_retransmission ( l2_softc_t *l2sc, int nr ); +extern void i4b_i_frame_queued_up ( l2_softc_t *l2sc ); +extern void i4b_l1_activate ( l2_softc_t *l2sc ); +extern int i4b_l2_nr_ok ( int nr, int va, int vs ); +extern void i4b_make_rand_ri ( l2_softc_t *l2sc ); +extern void i4b_mdl_assign_ind ( l2_softc_t *l2sc ); +extern void i4b_mdl_error_ind ( l2_softc_t *l2sc, char *where, int errorcode ); +extern int i4b_mph_attach_ind ( int unit, int type ); +extern int i4b_mph_status_ind ( int unit, int status, int parm ); +extern void i4b_next_l2state ( l2_softc_t *l2sc, int event ); +extern void i4b_nr_error_recovery ( l2_softc_t *l2sc ); +extern int i4b_ph_activate_ind ( int unit ); +extern int i4b_ph_deactivate_ind ( int unit ); +extern int i4b_ph_data_ind ( int unit, struct mbuf *m ); +extern void i4b_print_frame ( int len, u_char *buf ); +extern char *i4b_print_l2state ( l2_softc_t *l2sc ); +extern void i4b_print_l2var ( l2_softc_t *l2sc ); +extern void i4b_rxd_ack(l2_softc_t *l2sc, int nr); +extern void i4b_rxd_i_frame ( int unit, struct mbuf *m ); +extern void i4b_rxd_s_frame ( int unit, struct mbuf *m ); +extern void i4b_rxd_u_frame ( int unit, struct mbuf *m ); +extern void i4b_T200_restart ( l2_softc_t *l2sc ); +extern void i4b_T200_start ( l2_softc_t *l2sc ); +extern void i4b_T200_stop ( l2_softc_t *l2sc ); +extern void i4b_T202_start ( l2_softc_t *l2sc ); +extern void i4b_T202_stop ( l2_softc_t *l2sc ); +extern void i4b_T203_restart ( l2_softc_t *l2sc ); +extern void i4b_T203_start ( l2_softc_t *l2sc ); +extern void i4b_T203_stop ( l2_softc_t *l2sc ); +extern void i4b_tei_assign ( l2_softc_t *l2sc ); +extern void i4b_tei_chkresp ( l2_softc_t *l2sc ); +extern void i4b_tei_rxframe ( int unit, struct mbuf *m ); +extern void i4b_tei_verify ( l2_softc_t *l2sc ); +extern void i4b_transmit_enquire ( l2_softc_t *l2sc ); +extern void i4b_tx_disc ( l2_softc_t *l2sc, pbit_t pbit ); +extern void i4b_tx_dm ( l2_softc_t *l2sc, fbit_t fbit ); +extern void i4b_tx_frmr ( l2_softc_t *l2sc, fbit_t fbit ); +extern void i4b_tx_rej_response ( l2_softc_t *l2sc, fbit_t fbit ); +extern void i4b_tx_rnr_command ( l2_softc_t *l2sc, pbit_t pbit ); +extern void i4b_tx_rnr_response ( l2_softc_t *l2sc, fbit_t fbit ); +extern void i4b_tx_rr_command ( l2_softc_t *l2sc, pbit_t pbit ); +extern void i4b_tx_rr_response ( l2_softc_t *l2sc, fbit_t fbit ); +extern void i4b_tx_sabme ( l2_softc_t *l2sc, pbit_t pbit ); +extern void i4b_tx_ua ( l2_softc_t *l2sc, fbit_t fbit ); + +#endif /* _I4B_L2_H_ */ diff --git a/sys/i4b/layer2/i4b_l2fsm.c b/sys/i4b/layer2/i4b_l2fsm.c new file mode 100644 index 0000000..113167c --- /dev/null +++ b/sys/i4b/layer2/i4b_l2fsm.c @@ -0,0 +1,1593 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2fsm.c - layer 2 FSM + * ------------------------- + * + * $Id: i4b_l2fsm.c,v 1.13 1998/12/05 18:05:11 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:28:15 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +l2_softc_t l2_softc[ISIC_MAXUNIT]; + +static char *l2state_text[N_STATES] = { + "ST_TEI_UNAS", + "ST_ASG_AW_TEI", + "ST_EST_AW_TEI", + "ST_TEI_ASGD", + + "ST_AW_EST", + "ST_AW_REL", + "ST_MULTIFR", + "ST_TIMREC", + + "ST_SUBSET", + "Illegal State" +}; + +static char *l2event_text[N_EVENTS] = { + "EV_DLESTRQ", + "EV_DLUDTRQ", + "EV_MDASGRQ", + "EV_MDERRRS", + "EV_PSDEACT", + "EV_MDREMRQ", + "EV_RXSABME", + "EV_RXDISC", + "EV_RXUA", + "EV_RXDM", + "EV_T200EXP", + "EV_DLDATRQ", + "EV_DLRELRQ", + "EV_T203EXP", + "EV_OWNBUSY", + "EV_OWNRDY", + "EV_RXRR", + "EV_RXREJ", + "EV_RXRNR", + "EV_RXFRMR", + "Illegal Event" +}; + +static void F_TU01 __P((l2_softc_t *)); +static void F_TU03 __P((l2_softc_t *)); + +static void F_TA03 __P((l2_softc_t *)); +static void F_TA04 __P((l2_softc_t *)); +static void F_TA05 __P((l2_softc_t *)); + +static void F_TE03 __P((l2_softc_t *)); +static void F_TE04 __P((l2_softc_t *)); +static void F_TE05 __P((l2_softc_t *)); + +static void F_T01 __P((l2_softc_t *)); +static void F_T05 __P((l2_softc_t *)); +static void F_T06 __P((l2_softc_t *)); +static void F_T07 __P((l2_softc_t *)); +static void F_T08 __P((l2_softc_t *)); +static void F_T09 __P((l2_softc_t *)); +static void F_T10 __P((l2_softc_t *)); +static void F_T13 __P((l2_softc_t *)); + +static void F_AE01 __P((l2_softc_t *)); +static void F_AE05 __P((l2_softc_t *)); +static void F_AE06 __P((l2_softc_t *)); +static void F_AE07 __P((l2_softc_t *)); +static void F_AE08 __P((l2_softc_t *)); +static void F_AE09 __P((l2_softc_t *)); +static void F_AE10 __P((l2_softc_t *)); +static void F_AE11 __P((l2_softc_t *)); +static void F_AE12 __P((l2_softc_t *)); + +static void F_AR05 __P((l2_softc_t *)); +static void F_AR06 __P((l2_softc_t *)); +static void F_AR07 __P((l2_softc_t *)); +static void F_AR08 __P((l2_softc_t *)); +static void F_AR09 __P((l2_softc_t *)); +static void F_AR10 __P((l2_softc_t *)); +static void F_AR11 __P((l2_softc_t *)); + +static void F_MF01 __P((l2_softc_t *)); +static void F_MF05 __P((l2_softc_t *)); +static void F_MF06 __P((l2_softc_t *)); +static void F_MF07 __P((l2_softc_t *)); +static void F_MF08 __P((l2_softc_t *)); +static void F_MF09 __P((l2_softc_t *)); +static void F_MF10 __P((l2_softc_t *)); +static void F_MF11 __P((l2_softc_t *)); +static void F_MF12 __P((l2_softc_t *)); +static void F_MF13 __P((l2_softc_t *)); +static void F_MF14 __P((l2_softc_t *)); +static void F_MF15 __P((l2_softc_t *)); +static void F_MF16 __P((l2_softc_t *)); +static void F_MF17 __P((l2_softc_t *)); +static void F_MF18 __P((l2_softc_t *)); +static void F_MF19 __P((l2_softc_t *)); +static void F_MF20 __P((l2_softc_t *)); + +static void F_TR01 __P((l2_softc_t *)); +static void F_TR05 __P((l2_softc_t *)); +static void F_TR06 __P((l2_softc_t *)); +static void F_TR07 __P((l2_softc_t *)); +static void F_TR08 __P((l2_softc_t *)); +static void F_TR09 __P((l2_softc_t *)); +static void F_TR10 __P((l2_softc_t *)); +static void F_TR11 __P((l2_softc_t *)); +static void F_TR12 __P((l2_softc_t *)); +static void F_TR13 __P((l2_softc_t *)); +static void F_TR15 __P((l2_softc_t *)); +static void F_TR16 __P((l2_softc_t *)); +static void F_TR17 __P((l2_softc_t *)); +static void F_TR18 __P((l2_softc_t *)); +static void F_TR19 __P((l2_softc_t *)); +static void F_TR20 __P((l2_softc_t *)); +static void F_ILL __P((l2_softc_t *)); +static void F_NCNA __P((l2_softc_t *)); + +/*---------------------------------------------------------------------------* + * FSM illegal state default action + *---------------------------------------------------------------------------*/ +static void +F_ILL(l2_softc_t *l2sc) +{ + DBGL2(L2_F_ERR, "F_ILL", ("FSM function F_ILL executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM No change, No action + *---------------------------------------------------------------------------*/ +static void +F_NCNA(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_NCNA", ("FSM function F_NCNA executing\n")); +} + +/*---------------------------------------------------------------------------* + * layer 2 state transition table + *---------------------------------------------------------------------------*/ +struct l2state_tab { + void (*func) __P((l2_softc_t *)); /* function to execute */ + int newstate; /* next state */ +} l2state_tab[N_EVENTS][N_STATES] = { + +/* STATE: ST_TEI_UNAS, ST_ASG_AW_TEI, ST_EST_AW_TEI, ST_TEI_ASGD, ST_AW_EST, ST_AW_REL, ST_MULTIFR, ST_TIMREC, ST_SUBSET, ILLEGAL STATE */ +/* -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*EV_DLESTRQ*/{ {F_TU01, ST_EST_AW_TEI}, {F_NCNA, ST_EST_AW_TEI}, {F_ILL, ST_ILL}, {F_T01, ST_AW_EST}, {F_AE01, ST_AW_EST}, {F_ILL, ST_ILL}, {F_MF01, ST_AW_EST}, {F_TR01, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_DLUDTRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_MDASGRQ*/{ {F_TU03, ST_TEI_ASGD}, {F_TA03, ST_TEI_ASGD}, {F_TE03, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_MDERRRS*/{ {F_ILL, ST_ILL}, {F_TA04, ST_TEI_UNAS}, {F_TE04, ST_TEI_UNAS}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_PSDEACT*/{ {F_ILL, ST_ILL}, {F_TA05, ST_TEI_UNAS}, {F_TE05, ST_TEI_UNAS}, {F_T05, ST_TEI_ASGD}, {F_AE05, ST_TEI_ASGD}, {F_AR05, ST_TEI_ASGD}, {F_MF05, ST_TEI_ASGD}, {F_TR05, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_MDREMRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T06, ST_TEI_UNAS}, {F_AE06, ST_TEI_UNAS}, {F_AR06, ST_TEI_UNAS}, {F_MF06, ST_TEI_UNAS}, {F_TR06, ST_TEI_UNAS}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXSABME*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T07, ST_SUBSET}, {F_AE07, ST_AW_EST}, {F_AR07, ST_AW_REL}, {F_MF07, ST_MULTIFR}, {F_TR07, ST_MULTIFR}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXDISC */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T08, ST_TEI_ASGD}, {F_AE08, ST_AW_EST}, {F_AR08, ST_AW_REL}, {F_MF08, ST_TEI_ASGD}, {F_TR08, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXUA */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T09, ST_TEI_ASGD}, {F_AE09, ST_SUBSET}, {F_AR09, ST_SUBSET}, {F_MF09, ST_MULTIFR}, {F_TR09, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXDM */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T10, ST_SUBSET}, {F_AE10, ST_SUBSET}, {F_AR10, ST_SUBSET}, {F_MF10, ST_SUBSET}, {F_TR10, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_T200EXP*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_AE11, ST_SUBSET}, {F_AR11, ST_SUBSET}, {F_MF11, ST_TIMREC}, {F_TR11, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_DLDATRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_AE12, ST_AW_EST}, {F_ILL, ST_ILL}, {F_MF12, ST_MULTIFR}, {F_TR12, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_DLRELRQ*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_T13, ST_TEI_ASGD}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF13, ST_AW_REL}, {F_TR13, ST_AW_REL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_T203EXP*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF14, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_OWNBUSY*/{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF15, ST_MULTIFR}, {F_TR15, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_OWNRDY */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF16, ST_MULTIFR}, {F_TR16, ST_TIMREC}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXRR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF17, ST_SUBSET}, {F_TR17, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXREJ */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF18, ST_SUBSET}, {F_TR18, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXRNR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF19, ST_SUBSET}, {F_TR19, ST_SUBSET}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_RXFRMR */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_MF20, ST_AW_EST}, {F_TR20, ST_AW_EST}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} }, +/*EV_ILL */{ {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL} } +}; + +/*---------------------------------------------------------------------------* + * event handler, executes function and sets new state + *---------------------------------------------------------------------------*/ +void i4b_next_l2state(l2_softc_t *l2sc, int event) +{ + int currstate, newstate; + + /* check event number */ + if(event > N_EVENTS) + panic("i4b_l2fsm.c: event > N_EVENTS\n"); + + /* get current state and check it */ + if((currstate = l2sc->Q921_state) > N_STATES) /* failsafe */ + panic("i4b_l2fsm.c: currstate > N_STATES\n"); + + /* get new state and check it */ + if((newstate = l2state_tab[event][currstate].newstate) > N_STATES) + panic("i4b_l2fsm.c: newstate > N_STATES\n"); + + + if(newstate != ST_SUBSET) + { /* state function does NOT set new state */ + DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM event [%s]: [%s/%d => %s/%d]\n", + l2event_text[event], + l2state_text[currstate], currstate, + l2state_text[newstate], newstate)); + } + + /* execute state transition function */ + (*l2state_tab[event][currstate].func)(l2sc); + + if(newstate == ST_SUBSET) + { /* state function DOES set new state */ + DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM S-event [%s]: [%s => %s]\n", l2event_text[event], + l2state_text[currstate], + l2state_text[l2sc->Q921_state])); + } + + /* check for illegal new state */ + + if(newstate == ST_ILL) + { + newstate = currstate; + DBGL2(L2_F_ERR, "i4b_next_l2state", ("FSM illegal state, state = %s, event = %s!\n", + l2state_text[currstate], + l2event_text[event])); + } + + /* check if state machine function has to set new state */ + + if(newstate != ST_SUBSET) + l2sc->Q921_state = newstate; /* no, we set new state */ + + if(l2sc->postfsmfunc != NULL) + { + DBGL2(L2_F_MSG, "i4b_next_l2state", ("FSM executing postfsmfunc!\n")); + (*l2sc->postfsmfunc)(l2sc->postfsmarg); + l2sc->postfsmfunc = NULL; + } +} + +/*---------------------------------------------------------------------------* + * return pointer to current state description + *---------------------------------------------------------------------------*/ +char *i4b_print_l2state(l2_softc_t *l2sc) +{ + return((char *) l2state_text[l2sc->Q921_state]); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_UNAS event dl establish request + *---------------------------------------------------------------------------*/ +static void +F_TU01(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TU01", ("FSM function F_TU01 executing\n")); + i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_UNAS event mdl assign request + *---------------------------------------------------------------------------*/ +static void +F_TU03(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TU03", ("FSM function F_TU03 executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_ASG_AW_TEI event mdl assign request + *---------------------------------------------------------------------------*/ +static void +F_TA03(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TA03", ("FSM function F_TA03 executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_ASG_AW_TEI event mdl error response + *---------------------------------------------------------------------------*/ +static void +F_TA04(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TA04", ("FSM function F_TA04 executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_ASG_AW_TEI event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_TA05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TA05", ("FSM function F_TA05 executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_EST_AW_TEI event mdl assign request + *---------------------------------------------------------------------------*/ +static void +F_TE03(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TE03", ("FSM function F_TE03 executing\n")); + i4b_establish_data_link(l2sc); + l2sc->l3initiated = 1; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_EST_AW_TEI event mdl error response + *---------------------------------------------------------------------------*/ +static void +F_TE04(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TE04", ("FSM function F_TE04 executing\n")); + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_EST_AW_TEI event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_TE05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TE05", ("FSM function F_TE05 executing\n")); + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event dl establish request + *---------------------------------------------------------------------------*/ +static void +F_T01(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T01", ("FSM function F_T01 executing\n")); + i4b_establish_data_link(l2sc); + l2sc->l3initiated = 1; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_T05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T05", ("FSM function F_T05 executing\n")); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event mdl remove request + *---------------------------------------------------------------------------*/ +static void +F_T06(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T06", ("FSM function F_T06 executing\n")); +/*XXX*/ i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event rx'd SABME + *---------------------------------------------------------------------------*/ +static void +F_T07(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T07", ("FSM function F_T07 executing\n")); + +/* XXX */ +#ifdef NOTDEF + if(NOT able to establish) + { + i4b_tx_dm(l2sc, l2sc->rxd_PF); + l2sc->Q921_state = ST_TEI_ASGD; + return; + } +#endif + + i4b_clear_exception_conditions(l2sc); + + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); + + i4b_tx_ua(l2sc, l2sc->rxd_PF); + + l2sc->vs = 0; + l2sc->va = 0; + l2sc->vr = 0; + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Est_Ind_A; + + i4b_T203_start(l2sc); + + l2sc->Q921_state = ST_MULTIFR; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event rx'd DISC + *---------------------------------------------------------------------------*/ +static void +F_T08(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T08", ("FSM function F_T08 executing\n")); + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE); + i4b_tx_ua(l2sc, l2sc->rxd_PF); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event rx'd UA + *---------------------------------------------------------------------------*/ +static void +F_T09(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T09", ("FSM function F_T09 executing\n")); + i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_C); + i4b_mdl_error_ind(l2sc, "F_T09", MDL_ERR_D); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event rx'd DM + *---------------------------------------------------------------------------*/ +static void +F_T10(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T10", ("FSM function F_T10 executing\n")); + + if(l2sc->rxd_PF) + { + l2sc->Q921_state = ST_TEI_ASGD; + } + else + { +#ifdef NOTDEF + if(NOT able_to_etablish) + { + l2sc->Q921_state = ST_TEI_ASGD; + return; + } +#endif + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 1; + + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TEI_ASGD event dl release request + *---------------------------------------------------------------------------*/ +static void +F_T13(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_T13", ("FSM function F_T13 executing\n")); + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event dl establish request + *---------------------------------------------------------------------------*/ +static void +F_AE01(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE01", ("FSM function F_AE01 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->l3initiated = 1; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_AE05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE05", ("FSM function F_AE05 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event mdl remove request + *---------------------------------------------------------------------------*/ +static void +F_AE06(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE06", ("FSM function F_AE06 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + +/*XXX*/ i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event rx'd SABME + *---------------------------------------------------------------------------*/ +static void +F_AE07(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE07", ("FSM function F_AE07 executing\n")); + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); + i4b_tx_ua(l2sc, l2sc->rxd_PF); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event rx'd DISC + *---------------------------------------------------------------------------*/ +static void +F_AE08(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE08", ("FSM function F_AE08 executing\n")); + i4b_tx_dm(l2sc, l2sc->rxd_PF); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event rx'd UA + *---------------------------------------------------------------------------*/ +static void +F_AE09(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE09", ("FSM function F_AE09 executing\n")); + + if(l2sc->rxd_PF == 0) + { + i4b_mdl_error_ind(l2sc, "F_AE09", MDL_ERR_D); + l2sc->Q921_state = ST_AW_EST; + } + else + { + if(l2sc->l3initiated) + { + l2sc->l3initiated = 0; + l2sc->vr = 0; + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Est_Cnf_A; + } + else + { + if(l2sc->vs != l2sc->va) + { + i4b_Dcleanifq(&l2sc->i_queue); + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Est_Ind_A; + } + } + + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); + + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + + l2sc->vs = 0; + l2sc->va = 0; + + l2sc->Q921_state = ST_MULTIFR; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event rx'd DM + *---------------------------------------------------------------------------*/ +static void +F_AE10(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE10", ("FSM function F_AE10 executing\n")); + + if(l2sc->rxd_PF == 0) + { + l2sc->Q921_state = ST_AW_EST; + } + else + { + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + + l2sc->Q921_state = ST_TEI_ASGD; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event T200 expiry + *---------------------------------------------------------------------------*/ +static void +F_AE11(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE11", ("FSM function F_AE11 executing\n")); + + if(l2sc->RC >= N200) + { + i4b_Dcleanifq(&l2sc->i_queue); + + i4b_mdl_error_ind(l2sc, "F_AE11", MDL_ERR_G); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + l2sc->Q921_state = ST_TEI_ASGD; + } + else + { + l2sc->RC++; + + i4b_tx_sabme(l2sc, P1); + + i4b_T200_start(l2sc); + + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_EST event dl data request + *---------------------------------------------------------------------------*/ +static void +F_AE12(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AE12", ("FSM function F_AE12 executing\n")); + + if(l2sc->l3initiated == 0) + { + i4b_i_frame_queued_up(l2sc); + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_AR05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR05", ("FSM function F_AR05 executing\n")); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; + + i4b_T200_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event mdl remove request + *---------------------------------------------------------------------------*/ +static void +F_AR06(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR06", ("FSM function F_AR06 executing\n")); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; + + i4b_T200_stop(l2sc); + +/*XXX*/ i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event rx'd SABME + *---------------------------------------------------------------------------*/ +static void +F_AR07(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR07", ("FSM function F_AR07 executing\n")); + i4b_tx_dm(l2sc, l2sc->rxd_PF); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event rx'd DISC + *---------------------------------------------------------------------------*/ +static void +F_AR08(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR08", ("FSM function F_AR08 executing\n")); + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE); + i4b_tx_ua(l2sc, l2sc->rxd_PF); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event rx'd UA + *---------------------------------------------------------------------------*/ +static void +F_AR09(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR09", ("FSM function F_AR09 executing\n")); + + if(l2sc->rxd_PF) + { + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; + + i4b_T200_stop(l2sc); + + l2sc->Q921_state = ST_TEI_ASGD; + } + else + { + i4b_mdl_error_ind(l2sc, "F_AR09", MDL_ERR_D); + + l2sc->Q921_state = ST_AW_REL; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event rx'd DM + *---------------------------------------------------------------------------*/ +static void +F_AR10(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR10", ("FSM function F_AR10 executing\n")); + + if(l2sc->rxd_PF) + { + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; + + i4b_T200_stop(l2sc); + + l2sc->Q921_state = ST_TEI_ASGD; + } + else + { + l2sc->Q921_state = ST_AW_REL; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_AW_REL event T200 expiry + *---------------------------------------------------------------------------*/ +static void +F_AR11(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_AR11", ("FSM function F_AR11 executing\n")); + + if(l2sc->RC >= N200) + { + i4b_mdl_error_ind(l2sc, "F_AR11", MDL_ERR_H); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Cnf_A; + + l2sc->Q921_state = ST_TEI_ASGD; + } + else + { + l2sc->RC++; + + i4b_tx_disc(l2sc, P1); + + i4b_T200_start(l2sc); + + l2sc->Q921_state = ST_AW_REL; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event dl establish request + *---------------------------------------------------------------------------*/ +static void +F_MF01(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF01", ("FSM function F_MF01 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 1; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_MF05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF05", ("FSM function F_MF05 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + i4b_T203_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event mdl remove request + *---------------------------------------------------------------------------*/ +static void +F_MF06(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF06", ("FSM function F_MF06 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + i4b_T203_stop(l2sc); + +/*XXX*/ i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd SABME + *---------------------------------------------------------------------------*/ +static void +F_MF07(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF07", ("FSM function F_MF07 executing\n")); + + i4b_clear_exception_conditions(l2sc); + + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); + + i4b_tx_ua(l2sc, l2sc->rxd_PF); + + i4b_mdl_error_ind(l2sc, "F_MF07", MDL_ERR_F); + + if(l2sc->vs != l2sc->va) + { + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Est_Ind_A; + } + + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + + l2sc->vs = 0; + l2sc->va = 0; + l2sc->vr = 0; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd DISC + *---------------------------------------------------------------------------*/ +static void +F_MF08(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF08", ("FSM function F_MF08 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE); + i4b_tx_ua(l2sc, l2sc->rxd_PF); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + i4b_T203_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd UA + *---------------------------------------------------------------------------*/ +static void +F_MF09(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF09", ("FSM function F_MF09 executing\n")); + if(l2sc->rxd_PF) + i4b_mdl_error_ind(l2sc, "F_MF09", MDL_ERR_C); + else + i4b_mdl_error_ind(l2sc, "F_MF09", MDL_ERR_D); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd DM + *---------------------------------------------------------------------------*/ +static void +F_MF10(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF10", ("FSM function F_MF10 executing\n")); + + if(l2sc->rxd_PF) + { + i4b_mdl_error_ind(l2sc, "F_MF10", MDL_ERR_B); + + l2sc->Q921_state = ST_MULTIFR; + } + else + { + i4b_mdl_error_ind(l2sc, "F_MF10", MDL_ERR_E); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; + + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event T200 expiry + *---------------------------------------------------------------------------*/ +static void +F_MF11(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF11", ("FSM function F_MF11 executing\n")); + + l2sc->RC = 0; + + i4b_transmit_enquire(l2sc); + + l2sc->RC++; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event dl data request + *---------------------------------------------------------------------------*/ +static void +F_MF12(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF12", ("FSM function F_MF12 executing\n")); + + i4b_i_frame_queued_up(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event dl release request + *---------------------------------------------------------------------------*/ +static void +F_MF13(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF13", ("FSM function F_MF13 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->RC = 0; + + i4b_tx_disc(l2sc, P1); + + i4b_T203_stop(l2sc); + i4b_T200_restart(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event T203 expiry + *---------------------------------------------------------------------------*/ +static void +F_MF14(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF14", ("FSM function F_MF14 executing\n")); + + i4b_transmit_enquire(l2sc); + + l2sc->RC = 0; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event set own rx busy + *---------------------------------------------------------------------------*/ +static void +F_MF15(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF15", ("FSM function F_MF15 executing\n")); + + if(l2sc->own_busy == 0) + { + l2sc->own_busy = 1; + + i4b_tx_rnr_response(l2sc, F0); /* wrong in Q.921 03/93 p 64 */ + + l2sc->ack_pend = 0; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event clear own rx busy + *---------------------------------------------------------------------------*/ +static void +F_MF16(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF16", ("FSM function F_MF16 executing\n")); + + if(l2sc->own_busy != 0) + { + l2sc->own_busy = 0; + + i4b_tx_rr_response(l2sc, F0); /* wrong in Q.921 03/93 p 64 */ + + l2sc->ack_pend = 0; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd RR + *---------------------------------------------------------------------------*/ +static void +F_MF17(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF17", ("FSM function F_MF17 executing\n")); + + l2sc->peer_busy = 0; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + i4b_mdl_error_ind(l2sc, "F_MF17", MDL_ERR_A); + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + if(l2sc->rxd_NR == l2sc->vs) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_stop(l2sc); + i4b_T203_restart(l2sc); + } + else if(l2sc->rxd_NR != l2sc->va) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_restart(l2sc); + } + l2sc->Q921_state = ST_MULTIFR; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd REJ + *---------------------------------------------------------------------------*/ +static void +F_MF18(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF18", ("FSM function F_MF18 executing\n")); + + l2sc->peer_busy = 0; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + i4b_mdl_error_ind(l2sc, "F_MF18", MDL_ERR_A); + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + i4b_invoke_retransmission(l2sc, l2sc->rxd_NR); + l2sc->Q921_state = ST_MULTIFR; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd RNR + *---------------------------------------------------------------------------*/ +static void +F_MF19(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF19", ("FSM function F_MF19 executing\n")); + + l2sc->peer_busy = 1; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + i4b_mdl_error_ind(l2sc, "F_MF19", MDL_ERR_A); + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + i4b_T203_stop(l2sc); + i4b_T200_restart(l2sc); + l2sc->Q921_state = ST_MULTIFR; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_MULTIFR event rx'd FRMR + *---------------------------------------------------------------------------*/ +static void +F_MF20(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_MF20", ("FSM function F_MF20 executing\n")); + + i4b_mdl_error_ind(l2sc, "F_MF20", MDL_ERR_K); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event dl establish request + *---------------------------------------------------------------------------*/ +static void +F_TR01(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR01", ("FSM function F_TR01 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 1; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event persistent deactivation + *---------------------------------------------------------------------------*/ +static void +F_TR05(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR05", ("FSM function F_TR05 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event mdl remove request + *---------------------------------------------------------------------------*/ +static void +F_TR06(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR06", ("FSM function F_TR06 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); + +/*XXX*/ i4b_mdl_assign_ind(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd SABME + *---------------------------------------------------------------------------*/ +static void +F_TR07(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR07", ("FSM function F_TR07 executing\n")); + + i4b_clear_exception_conditions(l2sc); + + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_ACTIVE); + + i4b_tx_ua(l2sc, l2sc->rxd_PF); + + i4b_mdl_error_ind(l2sc, "F_TR07", MDL_ERR_F); + + if(l2sc->vs != l2sc->va) + { + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Est_Ind_A; + } + + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + + l2sc->vs = 0; + l2sc->va = 0; + l2sc->vr = 0; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd DISC + *---------------------------------------------------------------------------*/ +static void +F_TR08(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR08", ("FSM function F_TR08 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + MDL_Status_Ind(l2sc->unit, STI_L2STAT, LAYER_IDLE); + i4b_tx_ua(l2sc, l2sc->rxd_PF); + + l2sc->postfsmarg = l2sc->unit; + l2sc->postfsmfunc = DL_Rel_Ind_A; + + i4b_T200_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd UA + *---------------------------------------------------------------------------*/ +static void +F_TR09(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR09", ("FSM function F_TR09 executing\n")); + if(l2sc->rxd_PF) + i4b_mdl_error_ind(l2sc, "F_TR09", MDL_ERR_C); + else + i4b_mdl_error_ind(l2sc, "F_TR09", MDL_ERR_D); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd DM + *---------------------------------------------------------------------------*/ +static void +F_TR10(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR10", ("FSM function F_TR10 executing\n")); + + if(l2sc->rxd_PF) + { + i4b_mdl_error_ind(l2sc, "F_TR10", MDL_ERR_B); + } + else + { + i4b_mdl_error_ind(l2sc, "F_TR10", MDL_ERR_E); + } + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event T200 expiry + *---------------------------------------------------------------------------*/ +static void +F_TR11(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR11", ("FSM function F_TR11 executing\n")); + + if(l2sc->RC >= N200) + { + i4b_mdl_error_ind(l2sc, "F_TR11", MDL_ERR_I); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; + + l2sc->Q921_state = ST_AW_EST; + } + else + { + i4b_transmit_enquire(l2sc); + + l2sc->RC++; + + l2sc->Q921_state = ST_TIMREC; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event dl data request + *---------------------------------------------------------------------------*/ +static void +F_TR12(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR12", ("FSM function F_TR12 executing\n")); + + i4b_i_frame_queued_up(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event dl release request + *---------------------------------------------------------------------------*/ +static void +F_TR13(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR13", ("FSM function F_TR13 executing\n")); + + i4b_Dcleanifq(&l2sc->i_queue); + + l2sc->RC = 0; + + i4b_tx_disc(l2sc, P1); + + i4b_T200_restart(l2sc); +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event set own rx busy + *---------------------------------------------------------------------------*/ +static void +F_TR15(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR15", ("FSM function F_TR15 executing\n")); + + if(l2sc->own_busy == 0) + { + l2sc->own_busy = 1; + + i4b_tx_rnr_response(l2sc, F0); + + l2sc->ack_pend = 0; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event clear own rx busy + *---------------------------------------------------------------------------*/ +static void +F_TR16(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR16", ("FSM function F_TR16 executing\n")); + + if(l2sc->own_busy != 0) + { + l2sc->own_busy = 0; + + i4b_tx_rr_response(l2sc, F0); /* this is wrong */ + /* in Q.921 03/93 p 74 ! */ + l2sc->ack_pend = 0; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd RR + *---------------------------------------------------------------------------*/ +static void +F_TR17(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR17", ("FSM function F_TR17 executing\n")); + + l2sc->peer_busy = 0; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + i4b_invoke_retransmission(l2sc, l2sc->rxd_NR); + l2sc->Q921_state = ST_MULTIFR; + return; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + return; + } + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + l2sc->Q921_state = ST_TIMREC; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event + *---------------------------------------------------------------------------*/ +static void +F_TR18(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR18", ("FSM function F_TR18 executing\n")); + + l2sc->peer_busy = 0; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_stop(l2sc); + i4b_T203_start(l2sc); + i4b_invoke_retransmission(l2sc, l2sc->rxd_NR); + l2sc->Q921_state = ST_MULTIFR; + return; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + return; + } + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + l2sc->Q921_state = ST_TIMREC; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd RNR + *---------------------------------------------------------------------------*/ +static void +F_TR19(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR19", ("FSM function F_TR19 executing\n")); + + l2sc->peer_busy = 0; + + if(l2sc->rxd_CR == CR_CMD_FROM_NT) + { + if(l2sc->rxd_PF == 1) + { + i4b_enquiry_response(l2sc); + } + } + else + { + if(l2sc->rxd_PF == 1) + { + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + i4b_T200_restart(l2sc); + i4b_invoke_retransmission(l2sc, l2sc->rxd_NR); + l2sc->Q921_state = ST_MULTIFR; + return; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + return; + } + } + } + + if(i4b_l2_nr_ok(l2sc->rxd_NR, l2sc->va, l2sc->vs)) + { + l2sc->va = l2sc->rxd_NR; + l2sc->Q921_state = ST_TIMREC; + } + else + { + i4b_nr_error_recovery(l2sc); + l2sc->Q921_state = ST_AW_EST; + } +} + +/*---------------------------------------------------------------------------* + * FSM state ST_TIMREC event rx'd FRMR + *---------------------------------------------------------------------------*/ +static void +F_TR20(l2_softc_t *l2sc) +{ + DBGL2(L2_F_MSG, "F_TR20", ("FSM function F_TR20 executing\n")); + + i4b_mdl_error_ind(l2sc, "F_TR20", MDL_ERR_K); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; +} + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_l2fsm.h b/sys/i4b/layer2/i4b_l2fsm.h new file mode 100644 index 0000000..8f51068 --- /dev/null +++ b/sys/i4b/layer2/i4b_l2fsm.h @@ -0,0 +1,82 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2fsm.h - layer 2 FSM + * ------------------------- + * + * $Id: i4b_l2fsm.h,v 1.3 1998/12/05 18:05:13 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:28:39 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L2FSM_H_ +#define _I4B_L2FSM_H_ + +enum Q921_states { + ST_TEI_UNAS, /* TEI unassigned */ + ST_ASG_AW_TEI, /* assign awaiting TEI */ + ST_EST_AW_TEI, /* establish awaiting TEI */ + ST_TEI_ASGD, /* TEI assigned */ + + ST_AW_EST, /* awaiting establishment */ + ST_AW_REL, /* awaiting release */ + ST_MULTIFR, /* multiple frame established */ + ST_TIMREC, /* timer recovery */ + + ST_SUBSET, /* SUBroutine SETs new state */ + ST_ILL, /* illegal state */ + N_STATES /* number of states */ +}; + +enum Q921_events { + EV_DLESTRQ, /* dl establish req */ + EV_DLUDTRQ, /* dl unit data req */ + EV_MDASGRQ, /* mdl assign req */ + EV_MDERRRS, /* mdl error response */ + EV_PSDEACT, /* persistent deactivation */ + EV_MDREMRQ, /* mdl remove req */ + EV_RXSABME, /* rx'd SABME */ + EV_RXDISC, /* rx'd DISC */ + EV_RXUA, /* rx'd UA */ + EV_RXDM, /* rx'd DM */ + EV_T200EXP, /* T200 expired */ + EV_DLDATRQ, /* dl data req */ + EV_DLRELRQ, /* dl release req */ + EV_T203EXP, /* T203 expired */ + EV_OWNBUSY, /* set own rx busy */ + EV_OWNRDY, /* clear own rx busy */ + EV_RXRR, /* rx'd RR */ + EV_RXREJ, /* rx'd REJ */ + EV_RXRNR, /* rx'd RNR */ + EV_RXFRMR, /* rx'd FRMR */ + + EV_ILL, /* Illegal */ + N_EVENTS +}; + +#endif /* _I4B_L2FSM_H_ */ + diff --git a/sys/i4b/layer2/i4b_l2timer.c b/sys/i4b/layer2/i4b_l2timer.c new file mode 100644 index 0000000..3b45e807 --- /dev/null +++ b/sys/i4b/layer2/i4b_l2timer.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2timer.c - layer 2 timer handling + * -------------------------------------- + * + * $Id: i4b_l2timer.c,v 1.12 1998/12/05 18:05:15 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:29:13 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * Q.921 timer T200 timeout function + *---------------------------------------------------------------------------*/ +static void +i4b_T200_timeout(l2_softc_t *l2sc) +{ + DBGL2(L2_T_ERR, "i4b_T200_timeout", ("unit %d, RC = %d\n", l2sc->unit, l2sc->RC)); + i4b_next_l2state(l2sc, EV_T200EXP); +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T200 start + *---------------------------------------------------------------------------*/ +void +i4b_T200_start(l2_softc_t *l2sc) +{ + DBGL2(L2_T_MSG, "i4b_T200_start", ("unit %d\n", l2sc->unit)); + l2sc->T200 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + l2sc->T200_callout = timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF); +#else + timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF); +#endif +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T200 stop + *---------------------------------------------------------------------------*/ +void +i4b_T200_stop(l2_softc_t *l2sc) +{ + if(l2sc->T200 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, l2sc->T200_callout); +#else + untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc); +#endif + l2sc->T200 = TIMER_IDLE; + } + DBGL2(L2_T_MSG, "i4b_T200_stop", ("unit %d\n", l2sc->unit)); +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T200 restart + *---------------------------------------------------------------------------*/ +void +i4b_T200_restart(l2_softc_t *l2sc) +{ + if(l2sc->T200 != TIMER_IDLE) +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, l2sc->T200_callout); +#else + untimeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc); +#endif + else + l2sc->T200 = TIMER_ACTIVE; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + l2sc->T200_callout = timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF); +#else + timeout((TIMEOUT_FUNC_T)i4b_T200_timeout, (void *)l2sc, T200DEF); +#endif + + DBGL2(L2_T_MSG, "i4b_T200_restart", ("unit %d\n", l2sc->unit)); +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T202 timeout function + *---------------------------------------------------------------------------*/ +static void +i4b_T202_timeout(l2_softc_t *l2sc) +{ + DBGL2(L2_T_ERR, "i4b_T202_timeout", ("unit %d, N202 = %d\n", l2sc->unit, l2sc->N202)); + + if(--(l2sc->N202)) + { + (*l2sc->T202func)(l2sc); + } +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T202 start + *---------------------------------------------------------------------------*/ +void +i4b_T202_start(l2_softc_t *l2sc) +{ + DBGL2(L2_T_MSG, "i4b_T202_start", ("unit %d\n", l2sc->unit)); + l2sc->N202 = N202DEF; + l2sc->T202 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + l2sc->T202_callout = timeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, T202DEF); +#else + timeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, T202DEF); +#endif +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T202 stop + *---------------------------------------------------------------------------*/ +void +i4b_T202_stop(l2_softc_t *l2sc) +{ + if(l2sc->T202 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc, l2sc->T202_callout); +#else + untimeout((TIMEOUT_FUNC_T)i4b_T202_timeout, (void *)l2sc); +#endif + l2sc->T202 = TIMER_IDLE; + } + DBGL2(L2_T_MSG, "i4b_T202_stop", ("unit %d\n", l2sc->unit)); +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T203 timeout function + *---------------------------------------------------------------------------*/ +#if I4B_T203_ACTIVE +static void +i4b_T203_timeout(l2_softc_t *l2sc) +{ + DBGL2(L2_T_ERR, "i4b_T203_timeout", ("unit %d\n", l2sc->unit)); + i4b_next_l2state(l2sc, EV_T203EXP); +} +#endif + +/*---------------------------------------------------------------------------* + * Q.921 timer T203 start + *---------------------------------------------------------------------------*/ +void +i4b_T203_start(l2_softc_t *l2sc) +{ +#if I4B_T203_ACTIVE + DBGL2(L2_T_MSG, "i4b_T203_start", ("unit %d\n", l2sc->unit)); + l2sc->T203 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + l2sc->T203_callout = timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF); +#else + timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF); +#endif +#endif +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T203 stop + *---------------------------------------------------------------------------*/ +void +i4b_T203_stop(l2_softc_t *l2sc) +{ +#if I4B_T203_ACTIVE + if(l2sc->T203 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, l2sc->T203_callout); +#else + untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc); +#endif + l2sc->T203 = TIMER_IDLE; + } + DBGL2(L2_T_MSG, "i4b_T203_stop", ("unit %d\n", l2sc->unit)); +#endif +} + +/*---------------------------------------------------------------------------* + * Q.921 timer T203 restart + *---------------------------------------------------------------------------*/ +void +i4b_T203_restart(l2_softc_t *l2sc) +{ +#if I4B_T203_ACTIVE + if(l2sc->T203 != TIMER_IDLE) +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, l2sc->T203_callout); +#else + untimeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc); +#endif + else + l2sc->T203 = TIMER_ACTIVE; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + l2sc->T203_callout = timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF); +#else + timeout((TIMEOUT_FUNC_T)i4b_T203_timeout, (void *)l2sc, T203DEF); +#endif + + DBGL2(L2_T_MSG, "i4b_T203_restart", ("unit %d\n", l2sc->unit)); +#endif +} + +#endif /* NI4BQ921 > 0 */ + diff --git a/sys/i4b/layer2/i4b_lme.c b/sys/i4b/layer2/i4b_lme.c new file mode 100644 index 0000000..b179e94 --- /dev/null +++ b/sys/i4b/layer2/i4b_lme.c @@ -0,0 +1,160 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_lme.c - layer management entity + * ------------------------------------- + * + * $Id: i4b_lme.c,v 1.8 1998/12/05 18:05:19 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:29:25 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * mdl assign indication handler + *---------------------------------------------------------------------------*/ +void +i4b_mdl_assign_ind(l2_softc_t *l2sc) +{ + DBGL2(L2_PRIM, "MDL-ASSIGN-IND", ("unit %d\n", l2sc->unit)); + + i4b_l1_activate(l2sc); + + if(l2sc->tei_valid == TEI_VALID) + { + l2sc->T202func = (void(*)(void*))i4b_tei_verify; + l2sc->N202 = N202DEF; + i4b_tei_verify(l2sc); + } + else + { + l2sc->T202func = (void(*)(void*))i4b_tei_assign; + l2sc->N202 = N202DEF; + i4b_tei_assign(l2sc); + } +} + +/*---------------------------------------------------------------------------* + * i4b_mdl_error_ind handler (Q.921 01/94 pp 156) + *---------------------------------------------------------------------------*/ +void +i4b_mdl_error_ind(l2_softc_t *l2sc, char *where, int errorcode) +{ + static char *error_text[] = { + "MDL_ERR_A: rx'd unsolicited response - supervisory (F=1)", + "MDL_ERR_B: rx'd unsolicited response - DM (F=1)", + "MDL_ERR_C: rx'd unsolicited response - UA (F=1)", + "MDL_ERR_D: rx'd unsolicited response - UA (F=0)", + "MDL_ERR_E: rx'd unsolicited response - DM (F=0)", + "MDL_ERR_F: peer initiated re-establishment - SABME", + "MDL_ERR_G: unsuccessful transmission N200times - SABME", + "MDL_ERR_H: unsuccessful transmission N200times - DIS", + "MDL_ERR_I: unsuccessful transmission N200times - Status ENQ", + "MDL_ERR_J: other error - N(R) error", + "MDL_ERR_K: other error - rx'd FRMR response", + "MDL_ERR_L: other error - rx'd undefined frame", + "MDL_ERR_M: other error - receipt of I field not permitted", + "MDL_ERR_N: other error - rx'd frame with wrong size", + "MDL_ERR_O: other error - N201 error", + "MDL_ERR_MAX: i4b_mdl_error_ind called with wrong parameter!!!" + }; + + if(errorcode > MDL_ERR_MAX) + errorcode = MDL_ERR_MAX; + + DBGL2(L2_ERROR, "i4b_mdl_error_ind", ("unit = %d, location = %s\n", l2sc->unit, where)); + DBGL2(L2_ERROR, "i4b_mdl_error_ind", ("error = %s\n", error_text[errorcode])); + + switch(errorcode) + { + case MDL_ERR_A: + case MDL_ERR_B: + break; + + case MDL_ERR_C: + case MDL_ERR_D: + i4b_tei_verify(l2sc); + break; + + case MDL_ERR_E: + case MDL_ERR_F: + break; + + case MDL_ERR_G: + case MDL_ERR_H: + i4b_tei_verify(l2sc); + break; + + case MDL_ERR_I: + case MDL_ERR_J: + case MDL_ERR_K: + case MDL_ERR_L: + case MDL_ERR_M: + case MDL_ERR_N: + case MDL_ERR_O: + break; + + default: + break; + } +} + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_mbuf.c b/sys/i4b/layer2/i4b_mbuf.c new file mode 100644 index 0000000..6d085c3 --- /dev/null +++ b/sys/i4b/layer2/i4b_mbuf.c @@ -0,0 +1,245 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b - mbuf handling support routines + * ------------------------------------ + * + * $Id: i4b_mbuf.c,v 1.10 1998/12/05 18:05:20 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:29:44 1998] + * + *---------------------------------------------------------------------------*/ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/tty.h> +#include <sys/proc.h> +#include <sys/uio.h> +#include <sys/kernel.h> +#include <sys/socket.h> +#include <net/if.h> + +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#define I4B_MBUF_DEBUG +#undef I4B_MBUF_TYPE_DEBUG + +#ifdef I4B_MBUF_TYPE_DEBUG + +#ifdef __FreeBSD__ + +#define MT_DCHAN 42 +#define MT_BCHAN 43 + +#else /* NetBSD */ + +#define MT_DCHAN MT_DATA +#define MT_BCHAN MT_DATA + +#endif + +#define MT_I4B_D MT_DCHAN +#define MT_I4B_B MT_BCHAN + +#else /* ! I4B_MBUF_TYPE_DEBUG */ + +#define MT_I4B_D MT_DATA +#define MT_I4B_B MT_DATA + +#endif /* I4B_MBUF_TYPE_DEBUG */ + +/*---------------------------------------------------------------------------* + * allocate D-channel mbuf space + *---------------------------------------------------------------------------*/ +struct mbuf* +i4b_Dgetmbuf(int len) +{ + struct mbuf *m; + + if(len > MCLBYTES) /* if length > max extension size */ + { + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getmbuf: error - len(%d) > MCLBYTES(%d)\n", + len, MCLBYTES); +#endif + + return(NULL); + } + + MGETHDR(m, M_DONTWAIT, MT_I4B_D); /* get mbuf with pkthdr */ + + /* did we actually get the mbuf ? */ + + if(!m) + { + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getbuf: error - MGETHDR failed!\n"); +#endif + + return(NULL); + } + + if(len >= MHLEN) + { + MCLGET(m, M_DONTWAIT); + + if(!(m->m_flags & M_EXT)) + { + m_freem(m); + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getbuf: error - MCLGET failed, len(%d)\n", len); +#endif + + return (NULL); + } + } + + m->m_len = len; + + return(m); +} + +/*---------------------------------------------------------------------------* + * free a D-channel mbuf + *---------------------------------------------------------------------------*/ +void +i4b_Dfreembuf(struct mbuf *m) +{ + if(m) + m_freem(m); +} + +/*---------------------------------------------------------------------------* + * clear a D-channel ifqueue from data + *---------------------------------------------------------------------------*/ +void +i4b_Dcleanifq(struct ifqueue *ifq) +{ + struct mbuf *m; + int x = splimp(); + + while(!IF_QEMPTY(ifq)) + { + IF_DEQUEUE(ifq, m); + i4b_Dfreembuf(m); + } + + splx(x); +} + +/*---------------------------------------------------------------------------* + * allocate B-channel mbuf space + *---------------------------------------------------------------------------*/ +struct mbuf* +i4b_Bgetmbuf(int len) +{ + struct mbuf *m; + + if(len > MCLBYTES) /* if length > max extension size */ + { + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getmbuf: error - len(%d) > MCLBYTES(%d)\n", + len, MCLBYTES); +#endif + + return(NULL); + } + + MGETHDR(m, M_DONTWAIT, MT_I4B_B); /* get mbuf with pkthdr */ + + /* did we actually get the mbuf ? */ + + if(!m) + { + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getbuf: error - MGETHDR failed!\n"); +#endif + + return(NULL); + } + + if(len >= MHLEN) + { + MCLGET(m, M_DONTWAIT); + + if(!(m->m_flags & M_EXT)) + { + m_freem(m); + +#ifdef I4B_MBUF_DEBUG + printf("i4b_getbuf: error - MCLGET failed, len(%d)\n", len); +#endif + + return (NULL); + } + } + + m->m_len = len; + + return(m); +} + +/*---------------------------------------------------------------------------* + * free a B-channel mbuf + *---------------------------------------------------------------------------*/ +void +i4b_Bfreembuf(struct mbuf *m) +{ + if(m) + m_freem(m); +} + +/*---------------------------------------------------------------------------* + * clear a B-channel ifqueue from data + *---------------------------------------------------------------------------*/ +void +i4b_Bcleanifq(struct ifqueue *ifq) +{ + struct mbuf *m; + int x = splimp(); + + while(!IF_QEMPTY(ifq)) + { + IF_DEQUEUE(ifq, m); + i4b_Bfreembuf(m); + } + + splx(x); +} + +/* EOF */ diff --git a/sys/i4b/layer2/i4b_sframe.c b/sys/i4b/layer2/i4b_sframe.c new file mode 100644 index 0000000..f8d14ba --- /dev/null +++ b/sys/i4b/layer2/i4b_sframe.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_sframe.c - s frame handling routines + * ---------------------------------------- + * + * $Id: i4b_sframe.c,v 1.8 1998/12/05 18:05:21 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:30:02 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * process s frame + *---------------------------------------------------------------------------*/ +void +i4b_rxd_s_frame(int unit, struct mbuf *m) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + u_char *ptr = m->m_data; + + if(!((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI))))) + { + i4b_Dfreembuf(m); + return; + } + + l2sc->rxd_CR = GETCR(*(ptr + OFF_SAPI)); + l2sc->rxd_PF = GETSPF(*(ptr + OFF_SNR)); + l2sc->rxd_NR = GETSNR(*(ptr + OFF_SNR)); + + i4b_rxd_ack(l2sc, l2sc->rxd_NR); + + switch(*(ptr + OFF_SRCR)) + { + case RR: + DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd RR, N(R) = %d\n", l2sc->rxd_NR)); + i4b_next_l2state(l2sc, EV_RXRR); + break; + + case RNR: + DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd RNR, N(R) = %d\n", l2sc->rxd_NR)); + i4b_next_l2state(l2sc, EV_RXRNR); + break; + + case REJ: + DBGL2(L2_S_MSG, "i4b_rxd_s_frame", ("rx'd REJ, N(R) = %d\n", l2sc->rxd_NR)); + i4b_next_l2state(l2sc, EV_RXREJ); + break; + + default: + DBGL2(L2_S_ERR, "i4b_rxd_s_frame", ("ERROR, unknown code, frame = \n")); + i4b_print_frame(m->m_len, m->m_data); + break; + } + i4b_Dfreembuf(m); +} + +/*---------------------------------------------------------------------------* + * transmit RR command + *---------------------------------------------------------------------------*/ +void +i4b_tx_rr_command(l2_softc_t *l2sc, pbit_t pbit) +{ + struct mbuf *m; + + DBGL2(L2_S_MSG, "i4b_tx_rr_command", ("tx RR, unit = %d\n", l2sc->unit)); + + m = i4b_build_s_frame(l2sc, CR_CMD_TO_NT, pbit, RR); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit RR response + *---------------------------------------------------------------------------*/ +void +i4b_tx_rr_response(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_S_MSG, "i4b_tx_rr_response", ("tx RR, unit = %d\n", l2sc->unit)); + + m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, RR); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit RNR command + *---------------------------------------------------------------------------*/ +void +i4b_tx_rnr_command(l2_softc_t *l2sc, pbit_t pbit) +{ + struct mbuf *m; + + DBGL2(L2_S_MSG, "i4b_tx_rnr_command", ("tx RNR, unit = %d\n", l2sc->unit)); + + m = i4b_build_s_frame(l2sc, CR_CMD_TO_NT, pbit, RNR); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit RNR response + *---------------------------------------------------------------------------*/ +void +i4b_tx_rnr_response(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_S_MSG, "i4b_tx_rnr_response", ("tx RNR, unit = %d\n", l2sc->unit)); + + m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, RNR); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit REJ response + *---------------------------------------------------------------------------*/ +void +i4b_tx_rej_response(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_S_MSG, "i4b_tx_rej_response", ("tx REJ, unit = %d\n", l2sc->unit)); + + m = i4b_build_s_frame(l2sc, CR_RSP_TO_NT, fbit, REJ); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * build S-frame for sending + *---------------------------------------------------------------------------*/ +struct mbuf * +i4b_build_s_frame(l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(S_FRAME_LEN)) == NULL) + return(NULL); + + PUTSAPI(SAPI_CCP, crbit, m->m_data[OFF_SAPI]); + + PUTTEI(l2sc->tei, m->m_data[OFF_TEI]); + + m->m_data[OFF_SRCR] = type; + + m->m_data[OFF_SNR] = (l2sc->vr << 1) | (pbit & 0x01); + + return(m); +} + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_tei.c b/sys/i4b/layer2/i4b_tei.c new file mode 100644 index 0000000..5c5b7b8 --- /dev/null +++ b/sys/i4b/layer2/i4b_tei.c @@ -0,0 +1,322 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tei.c - tei handling procedures + * ----------------------------------- + * + * $Id: i4b_tei.c,v 1.13 1998/12/05 18:05:23 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:30:20 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/syslog.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <machine/random.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * handle a received TEI management frame + *---------------------------------------------------------------------------*/ +void +i4b_tei_rxframe(int unit, struct mbuf *m) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + u_char *ptr = m->m_data; + + switch(*(ptr + OFF_MT)) + { + case MT_ID_ASSIGN: + if( (*(ptr + OFF_RIL) == l2sc->last_ril) && + (*(ptr + OFF_RIH) == l2sc->last_rih)) + { + l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI)); + l2sc->tei_valid = TEI_VALID; + + if(l2sc->T202 == TIMER_ACTIVE) + i4b_T202_stop(l2sc); + + MDL_Status_Ind(l2sc->unit, STI_TEIASG, l2sc->tei); + + log(LOG_INFO, "i4b: unit %d, assigned TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei); + + DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Assign - TEI = %d\n", l2sc->tei)); + + i4b_next_l2state(l2sc, EV_MDASGRQ); + } + break; + + case MT_ID_DENY: + if( (*(ptr + OFF_RIL) == l2sc->last_ril) && + (*(ptr + OFF_RIH) == l2sc->last_rih)) + { + l2sc->tei_valid = TEI_INVALID; + l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI)); + + if(l2sc->tei == GROUP_TEI) + { + log(LOG_WARNING, "i4b: unit %d, denied TEI, no TEI values available from exchange!\n", l2sc->unit); + DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("TEI ID Denied, No TEI values available from exchange!\n")); + } + else + { + log(LOG_WARNING, "i4b: unit %d, denied TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei); + DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("TEI ID Denied - TEI = %d\n", l2sc->tei)); + } + MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1); + i4b_next_l2state(l2sc, EV_MDERRRS); + } + break; + + case MT_ID_CHK_REQ: + if( (l2sc->tei_valid == TEI_VALID) && + ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) || + (GROUP_TEI == GET_TEIFROMAI(*(ptr+OFF_AI))) )) + { + static int lasttei = -1; + + if(l2sc->tei != lasttei) + { + DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Check Req - TEI = %d\n", l2sc->tei)); + lasttei = l2sc->tei; + } + + if(l2sc->T202 == TIMER_ACTIVE) + i4b_T202_stop(l2sc); + i4b_tei_chkresp(l2sc); + } + break; + + case MT_ID_REMOVE: + if( (l2sc->tei_valid == TEI_VALID) && + ( (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))) || + (l2sc->tei == GET_TEIFROMAI(*(ptr+OFF_AI))))) + { + l2sc->tei_valid = TEI_INVALID; + l2sc->tei = GET_TEIFROMAI(*(ptr+OFF_AI)); + + log(LOG_INFO, "i4b: unit %d, removed TEI = %d = 0x%02x\n", l2sc->unit, l2sc->tei, l2sc->tei); + DBGL2(L2_TEI_MSG, "i4b_tei_rx_frame", ("TEI ID Remove - TEI = %d\n", l2sc->tei)); + MDL_Status_Ind(l2sc->unit, STI_TEIASG, -1); + i4b_next_l2state(l2sc, EV_MDREMRQ); + } + break; + + default: + DBGL2(L2_TEI_ERR, "i4b_tei_rx_frame", ("UNKNOWN TEI MGMT Frame, type = 0x%x\n", *(ptr + OFF_MT))); + i4b_print_frame(m->m_len, m->m_data); + break; + } + i4b_Dfreembuf(m); +} + +/*---------------------------------------------------------------------------* + * allocate and fill up a TEI management frame for sending + *---------------------------------------------------------------------------*/ +static struct mbuf * +build_tei_mgmt_frame(l2_softc_t *l2sc, unsigned char type) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(TEI_MGMT_FRM_LEN)) == NULL) + return(NULL); + + m->m_data[TEIM_SAPIO] = 0xfc; /* SAPI = 63, CR = 0, EA = 0 */ + m->m_data[TEIM_TEIO] = 0xff; /* TEI = 127, EA = 1 */ + m->m_data[TEIM_UIO] = UI; /* UI */ + m->m_data[TEIM_MEIO] = MEI; /* MEI */ + m->m_data[TEIM_MTO] = type; /* message type */ + + switch(type) + { + case MT_ID_REQEST: + i4b_make_rand_ri(l2sc); + m->m_data[TEIM_RILO] = l2sc->last_ril; + m->m_data[TEIM_RIHO] = l2sc->last_rih; + m->m_data[TEIM_AIO] = (GROUP_TEI << 1) | 0x01; + break; + + case MT_ID_CHK_RSP: + i4b_make_rand_ri(l2sc); + m->m_data[TEIM_RILO] = l2sc->last_ril; + m->m_data[TEIM_RIHO] = l2sc->last_rih; + m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01; + break; + + case MT_ID_VERIFY: + m->m_data[TEIM_RILO] = 0; + m->m_data[TEIM_RIHO] = 0; + m->m_data[TEIM_AIO] = (l2sc->tei << 1) | 0x01; + break; + + default: + i4b_Dfreembuf(m); + panic("build_tei_mgmt_frame: invalid type"); + break; + } + return(m); +} + +/*---------------------------------------------------------------------------* + * i4b_tei_assign - TEI assignment procedure (Q.921, 5.3.2, pp 24) + * T202func and N202 _MUST_ be set prior to calling this function ! + *---------------------------------------------------------------------------*/ +void +i4b_tei_assign(l2_softc_t *l2sc) +{ + struct mbuf *m; + + DBGL2(L2_TEI_MSG, "i4b_tei_assign", ("tx TEI ID_Request\n")); + + m = build_tei_mgmt_frame(l2sc, MT_ID_REQEST); + + if(m == NULL) + panic("i4b_tei_assign: no mbuf"); + + i4b_T202_start(l2sc); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * i4b_tei_assign - TEI verify procedure (Q.921, 5.3.5, pp 29) + * T202func and N202 _MUST_ be set prior to calling this function ! + *---------------------------------------------------------------------------*/ +void +i4b_tei_verify(l2_softc_t *l2sc) +{ + struct mbuf *m; + + DBGL2(L2_TEI_MSG, "i4b_tei_verify", ("tx TEI ID_Verify\n")); + + m = build_tei_mgmt_frame(l2sc, MT_ID_VERIFY); + + if(m == NULL) + panic("i4b_tei_verify: no mbuf"); + + i4b_T202_start(l2sc); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * i4b_tei_chkresp - TEI check response procedure (Q.921, 5.3.5, pp 29) + *---------------------------------------------------------------------------*/ +void +i4b_tei_chkresp(l2_softc_t *l2sc) +{ + struct mbuf *m; + static int lasttei = 0; + + if(l2sc->tei != lasttei) + { + lasttei = l2sc->tei; + DBGL2(L2_TEI_MSG, "i4b_tei_chkresp", ("tx TEI ID_Check_Response\n")); + } + + m = build_tei_mgmt_frame(l2sc, MT_ID_CHK_RSP); + + if(m == NULL) + panic("i4b_tei_chkresp: no mbuf"); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * generate some 16 bit "random" number used for TEI mgmt Ri field + *---------------------------------------------------------------------------*/ +void +i4b_make_rand_ri(l2_softc_t *l2sc) +{ + +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + + u_short val; + read_random((char *)&val, sizeof(val)); + +#else + + register u_short val; + register int i; + static int called = 42; + + val = (l2sc->last_rih << 8) | l2sc->last_ril; + + val += ++called; + + for(i=0; i < 50 ; i++, val++) + { + val |= l2sc->unit+i; + val <<= i; + val ^= (time.tv_sec >> 16) ^ time.tv_usec; + val <<= i; + val ^= time.tv_sec ^ (time.tv_usec >> 16); + + if(val != 0 && val != 0xffff) + break; + } +#endif + l2sc->last_rih = (val >> 8) & 0x00ff; + l2sc->last_ril = val & 0x00ff; +} + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_uframe.c b/sys/i4b/layer2/i4b_uframe.c new file mode 100644 index 0000000..90e7912 --- /dev/null +++ b/sys/i4b/layer2/i4b_uframe.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_uframe.c - routines for handling U-frames + * ----------------------------------------------- + * + * $Id: i4b_uframe.c,v 1.6 1998/12/05 18:05:24 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:30:33 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * process a received U-frame + *---------------------------------------------------------------------------*/ +void +i4b_rxd_u_frame(int unit, struct mbuf *m) +{ + l2_softc_t *l2sc = &l2_softc[unit]; + u_char *ptr = m->m_data; + + int sapi = GETSAPI(*(ptr + OFF_SAPI)); + int tei = GETTEI(*(ptr + OFF_TEI)); + int pfbit = GETUPF(*(ptr + OFF_CNTL)); + + switch(*(ptr + OFF_CNTL) & ~UPFBIT) + { + /* commands */ + + case SABME: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("SABME, sapi = %d, tei = %d\n", sapi, tei)); + + l2sc->rxd_PF = pfbit; + + i4b_next_l2state(l2sc, EV_RXSABME); + } + i4b_Dfreembuf(m); + break; + + case UI: + if(sapi == SAPI_L2M && + tei == GROUP_TEI && + *(ptr + OFF_MEI) == MEI) + { + /* layer 2 management (SAPI = 63) */ + + i4b_tei_rxframe(unit, m); + } + else if(sapi == SAPI_CCP && tei == GROUP_TEI) + { + /* call control (SAPI = 0) */ + + /* strip ui header */ + m_adj(m, UI_HDR_LEN); + /* to upper layer */ + DL_Unit_Data_Ind(unit, m); + } + else + { + DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("unknown UI frame!\n")); + + i4b_Dfreembuf(m); + } + break; + + case DISC: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("DISC, sapi = %d, tei = %d\n", sapi, tei)); + + l2sc->rxd_PF = pfbit; + + i4b_next_l2state(l2sc, EV_RXDISC); + } + i4b_Dfreembuf(m); + break; + + case XID: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("XID, sapi = %d, tei = %d\n", sapi, tei)); + } + i4b_Dfreembuf(m); + break; + + /* responses */ + + case DM: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("DM, sapi = %d, tei = %d\n", sapi, tei)); + + i4b_print_frame(m->m_len, m->m_data); + + l2sc->rxd_PF = pfbit; + + i4b_next_l2state(l2sc, EV_RXDM); + } + i4b_Dfreembuf(m); + break; + + case UA: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("UA, sapi = %d, tei = %d\n", sapi, tei)); + + l2sc->rxd_PF = pfbit; + + i4b_next_l2state(l2sc, EV_RXUA); + } + i4b_Dfreembuf(m); + break; + + case FRMR: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_MSG, "i4b_rxd_u_frame", ("FRMR, sapi = %d, tei = %d\n", sapi, tei)); + + l2sc->rxd_PF = pfbit; + + i4b_next_l2state(l2sc, EV_RXFRMR); + } + i4b_Dfreembuf(m); + break; + + default: + if((l2sc->tei_valid == TEI_VALID) && + (l2sc->tei == GETTEI(*(ptr+OFF_TEI)))) + { + DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei)); + i4b_print_frame(m->m_len, m->m_data); + } + else + { + DBGL2(L2_U_ERR, "i4b_rxd_u_frame", ("not mine - UNKNOWN TYPE ERROR, sapi = %d, tei = %d, frame = ", sapi, tei)); + i4b_print_frame(m->m_len, m->m_data); + } + i4b_Dfreembuf(m); + break; + } +} + +/*---------------------------------------------------------------------------* + * build U-frame for sending + *---------------------------------------------------------------------------*/ +struct mbuf * +i4b_build_u_frame(l2_softc_t *l2sc, crbit_to_nt_t crbit, pbit_t pbit, u_char type) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(U_FRAME_LEN)) == NULL) + return(NULL); + + PUTSAPI(SAPI_CCP, crbit, m->m_data[OFF_SAPI]); + + PUTTEI(l2sc->tei, m->m_data[OFF_TEI]); + + if(pbit) + m->m_data[OFF_CNTL] = type | UPBITSET; + else + m->m_data[OFF_CNTL] = type & ~UPBITSET; + + return(m); +} + +/*---------------------------------------------------------------------------* + * transmit SABME command + *---------------------------------------------------------------------------*/ +void +i4b_tx_sabme(l2_softc_t *l2sc, pbit_t pbit) +{ + struct mbuf *m; + + DBGL2(L2_U_MSG, "i4b_tx_sabme", ("tx SABME, tei = %d\n", l2sc->tei)); + + m = i4b_build_u_frame(l2sc, CR_CMD_TO_NT, pbit, SABME); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit DM response + *---------------------------------------------------------------------------*/ +void +i4b_tx_dm(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_U_MSG, "i4b_tx_dm", ("tx DM, tei = %d\n", l2sc->tei)); + + m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, DM); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit DISC command + *---------------------------------------------------------------------------*/ +void +i4b_tx_disc(l2_softc_t *l2sc, pbit_t pbit) +{ + struct mbuf *m; + + DBGL2(L2_U_MSG, "i4b_tx_disc", ("tx DISC, tei = %d\n", l2sc->tei)); + + m = i4b_build_u_frame(l2sc, CR_CMD_TO_NT, pbit, DISC); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit UA response + *---------------------------------------------------------------------------*/ +void +i4b_tx_ua(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_U_MSG, "i4b_tx_ua", ("tx UA, tei = %d\n", l2sc->tei)); + + m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, UA); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + +/*---------------------------------------------------------------------------* + * transmit FRMR response + *---------------------------------------------------------------------------*/ +void +i4b_tx_frmr(l2_softc_t *l2sc, fbit_t fbit) +{ + struct mbuf *m; + + DBGL2(L2_U_MSG, "i4b_tx_frmr", ("tx FRMR, tei = %d\n", l2sc->tei)); + + m = i4b_build_u_frame(l2sc, CR_RSP_TO_NT, fbit, FRMR); + + PH_Data_Req(l2sc->unit, m, MBUF_FREE); +} + + +#endif /* NI4BQ921 > 0 */ diff --git a/sys/i4b/layer2/i4b_util.c b/sys/i4b/layer2/i4b_util.c new file mode 100644 index 0000000..9f8fe19 --- /dev/null +++ b/sys/i4b/layer2/i4b_util.c @@ -0,0 +1,312 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_util.c - layer 2 utility routines + * ------------------------------------- + * + * $Id: i4b_util.c,v 1.15 1998/12/05 18:05:26 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:31:10 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq921.h" +#else +#define NI4BQ921 1 +#endif +#if NI4BQ921 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l1l2.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer2/i4b_l2.h> +#include <i4b/layer2/i4b_l2fsm.h> + +/*---------------------------------------------------------------------------* + * routine ESTABLISH DATA LINK (Q.921 03/93 page 83) + *---------------------------------------------------------------------------*/ +void +i4b_establish_data_link(l2_softc_t *l2sc) +{ + i4b_l1_activate(l2sc); + + i4b_clear_exception_conditions(l2sc); + + l2sc->RC = 0; + + i4b_tx_sabme(l2sc, P1); + + i4b_T200_restart(l2sc); + + i4b_T203_stop(l2sc); +} + +/*---------------------------------------------------------------------------* + * routine CLEAR EXCEPTION CONDITIONS (Q.921 03/93 page 83) + *---------------------------------------------------------------------------*/ +void +i4b_clear_exception_conditions(l2_softc_t *l2sc) +{ + +/*XXX -------------------------------------------------------------- */ +/*XXX is this really appropriate here or should it moved elsewhere ? */ + + i4b_Dcleanifq(&l2sc->i_queue); + + if(l2sc->ua_num != UA_EMPTY) + { + i4b_Dfreembuf(l2sc->ua_frame); + l2sc->ua_num = UA_EMPTY; + } +/*XXX -------------------------------------------------------------- */ + + l2sc->peer_busy = 0; + + l2sc->rej_excpt = 0; + + l2sc->own_busy = 0; + + l2sc->ack_pend = 0; +} + +/*---------------------------------------------------------------------------* + * routine TRANSMIT ENQUIRE (Q.921 03/93 page 83) + *---------------------------------------------------------------------------*/ +void +i4b_transmit_enquire(l2_softc_t *l2sc) +{ + if(l2sc->own_busy) + i4b_tx_rnr_command(l2sc, P1); + else + i4b_tx_rr_command(l2sc, P1); + + l2sc->ack_pend = 0; + + i4b_T200_start(l2sc); +} + +/*---------------------------------------------------------------------------* + * routine NR ERROR RECOVERY (Q.921 03/93 page 83) + *---------------------------------------------------------------------------*/ +void +i4b_nr_error_recovery(l2_softc_t *l2sc) +{ + i4b_mdl_error_ind(l2sc, "i4b_nr_error_recovery", MDL_ERR_J); + + i4b_establish_data_link(l2sc); + + l2sc->l3initiated = 0; +} + +/*---------------------------------------------------------------------------* + * routine ENQUIRY RESPONSE (Q.921 03/93 page 84) + *---------------------------------------------------------------------------*/ +void +i4b_enquiry_response(l2_softc_t *l2sc) +{ + if(l2sc->own_busy) + i4b_tx_rnr_response(l2sc, F1); + else + i4b_tx_rr_response(l2sc, F1); + + l2sc->ack_pend = 0; +} + +/*---------------------------------------------------------------------------* + * routine INVOKE RETRANSMISSION (Q.921 03/93 page 84) + *---------------------------------------------------------------------------*/ +void +i4b_invoke_retransmission(l2_softc_t *l2sc, int nr) +{ + DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("nr = %d\n", nr )); + + while(l2sc->vs != nr) + { + DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("nr != vs, nr = %d, vs = %d\n", nr, l2sc->vs)); + + M128DEC(l2sc->vs); + +/* XXXXXXXXXXXXXXXXX */ + + if((l2sc->ua_num != UA_EMPTY) && (l2sc->vs == l2sc->ua_num)) + { + IF_ENQUEUE(&l2sc->i_queue, l2sc->ua_frame); + l2sc->ua_num = UA_EMPTY; + } + else + { + DBGL2(L2_ERROR, "i4b_invoke_retransmission", ("ERROR, l2sc->vs = %d, l2sc->ua_num = %d \n",l2sc->vs, l2sc->ua_num)); + } + +/* XXXXXXXXXXXXXXXXX */ + + i4b_i_frame_queued_up(l2sc); + } +} + +/*---------------------------------------------------------------------------* + * routine ACKNOWLEDGE PENDING (Q.921 03/93 p 70) + *---------------------------------------------------------------------------*/ +void +i4b_acknowledge_pending(l2_softc_t *l2sc) +{ + if(l2sc->ack_pend) + { + l2sc->ack_pend = 0; + i4b_tx_rr_response(l2sc, F0); + } +} + +/*---------------------------------------------------------------------------* + * i4b_print_frame - just print the hex contents of a frame + *---------------------------------------------------------------------------*/ +void +i4b_print_frame(int len, u_char *buf) +{ +#ifdef DO_I4B_DEBUG + int i; + + if (!(i4b_l2_debug & L2_ERROR)) /* XXXXXXXXXXXXXXXXXXXXX */ + return; + + for(i = 0; i < len; i++) + printf(" 0x%x", buf[i]); + printf("\n"); +#endif +} + +/*---------------------------------------------------------------------------* + * i4b_print_l2var - print some l2softc vars + *---------------------------------------------------------------------------*/ +void +i4b_print_l2var(l2_softc_t *l2sc) +{ + DBGL2(L2_ERROR, "i4b_print_l2var", ("unit%d V(R)=%d, V(S)=%d, V(A)=%d,ACKP=%d,PBSY=%d,OBSY=%d\n", + l2sc->unit, + l2sc->vr, + l2sc->vs, + l2sc->va, + l2sc->ack_pend, + l2sc->peer_busy, + l2sc->own_busy)); +} + +/*---------------------------------------------------------------------------* + * got s or i frame, check if valid ack for last sent frame + *---------------------------------------------------------------------------*/ +void +i4b_rxd_ack(l2_softc_t *l2sc, int nr) +{ + +#ifdef NOTDEF + DBGL2(L2_ERROR, "i4b_rxd_ack", ("N(R)=%d, UA=%d, V(R)=%d, V(S)=%d, V(A)=%d\n", + nr, + l2sc->ua_num, + l2sc->vr, + l2sc->vs, + l2sc->va)); +#endif + + if(l2sc->ua_num != UA_EMPTY) + { + int s; + + M128DEC(nr); + + if(l2sc->ua_num != nr) + DBGL2(L2_ERROR, "i4b_rxd_ack", ("((N(R)-1)=%d) != (UA=%d) !!!\n", nr, l2sc->ua_num)); + + s = SPLI4B(); + + i4b_Dfreembuf(l2sc->ua_frame); + l2sc->ua_num = UA_EMPTY; + + splx(s); + } +} + +/*---------------------------------------------------------------------------* + * if not already active, activate layer 1 + *---------------------------------------------------------------------------*/ +void +i4b_l1_activate(l2_softc_t *l2sc) +{ + if(l2sc->ph_active == PH_INACTIVE) + { + l2sc->ph_active = PH_ACTIVEPEND; + PH_Act_Req(l2sc->unit); + } +}; + +/*---------------------------------------------------------------------------* + * check for v(a) <= n(r) <= v(s) + * nr = receive sequence frame counter, va = acknowledge sequence frame + * counter and vs = transmit sequence frame counter + *---------------------------------------------------------------------------*/ +int +i4b_l2_nr_ok(int nr, int va, int vs) +{ + if((va > nr) && ((nr != 0) || (va != 127))) + { + DBGL2(L2_ERROR, "i4b_l2_nr_ok", ("ERROR, va = %d, nr = %d, vs = %d [1]\n", va, nr, vs)); + return 0; /* fail */ + } + + if((nr > vs) && ((vs != 0) || (nr != 127))) + { + DBGL2(L2_ERROR, "i4b_l2_nr_ok", ("ERROR, va = %d, nr = %d, vs = %d [2]\n", va, nr, vs)); + return 0; /* fail */ + } + + return 1; /* good */ +} + +#endif /* NI4BQ921 > 0 */ + diff --git a/sys/i4b/layer3/i4b_l2if.c b/sys/i4b/layer3/i4b_l2if.c new file mode 100644 index 0000000..33b1340 --- /dev/null +++ b/sys/i4b/layer3/i4b_l2if.c @@ -0,0 +1,642 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l2if.c - Layer 3 interface to Layer 2 + * ------------------------------------------- + * + * $Id: i4b_l2if.c,v 1.14 1998/12/05 18:05:28 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:31:26 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> + +#include <i4b/layer4/i4b_l4.h> + +static unsigned char make_q931_cause(cause_t cause); + +/*---------------------------------------------------------------------------* + * this converts our internal state (number) to the number specified + * in Q.931 and is used for reporting our state in STATUS messages. + *---------------------------------------------------------------------------*/ +int i4b_status_tab[] = { + 0, /* ST_U0, */ + 1, /* ST_U1, */ + 3, /* ST_U3, */ + 4, /* ST_U4, */ + 6, /* ST_U6, */ + 7, /* ST_U7, */ + 8, /* ST_U8, */ + 9, /* ST_U9, */ + 10, /* ST_U10, */ + 11, /* ST_U11, */ + 12, /* ST_U12, */ + 19, /* ST_U19, */ + 6, /* ST_IWA, */ + 6, /* ST_IWR, */ + 1, /* ST_OW, */ + 6, /* ST_IWL, */ +}; + +/*---------------------------------------------------------------------------* + * return a valid q.931/q.850 cause from any of the internal causes + *---------------------------------------------------------------------------*/ +static unsigned char +make_q931_cause(cause_t cause) +{ + register unsigned char ret; + + switch(GET_CAUSE_TYPE(cause)) + { + case CAUSET_Q850: + ret = GET_CAUSE_VAL(cause); + break; + case CAUSET_I4B: + ret = cause_tab_q931[GET_CAUSE_VAL(cause)]; + break; + default: + panic("make_q931_cause: unknown cause type!"); + break; + } + ret |= EXT_LAST; + return(ret); +} + +/*---------------------------------------------------------------------------* + * return status of data link + *---------------------------------------------------------------------------*/ +int +i4b_get_dl_stat(call_desc_t *cd) +{ + return(ctrl_desc[cd->controller].dl_est); +} + +/*---------------------------------------------------------------------------* + * DL ESTABLISH INDICATION from Layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_establish_ind(int unit) +{ + int i; + int found = 0; + + DBGL2(L2_PRIM, "DL-ESTABLISH-IND", ("unit %d\n",unit)); + + /* first set DL up in controller descriptor */ + + for(i=0; i < nctrl; i++) + { + if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[i].unit == unit)) + { + DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d DL established!\n",unit)); + ctrl_desc[i].dl_est = DL_UP; + found = 1; + } + } + + if(found == 0) + { + DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, controller not found for unit=%d!\n",unit)); + return(-1); + } + + found = 0; + + /* second, inform all (!) active call of the event */ + + for(i=0; i < N_CALL_DESC; i++) + { + if( (call_desc[i].cdid != 0) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + DBGL3(L3_MSG, "i4b_dl_establish_ind", ("unit=%d, index=%d cdid=%u cr=%d\n", + unit, i, call_desc[i].cdid, call_desc[i].cr)); + next_l3state(&call_desc[i], EV_DLESTIN); + found++; + } + } + + if(found == 0) + { + DBGL3(L3_ERR, "i4b_dl_establish_ind", ("ERROR, no cdid for unit %d found!\n", unit)); + return(-1); + } + else + { + return(0); + } +} + +/*---------------------------------------------------------------------------* + * DL ESTABLISH CONFIRM from Layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_establish_cnf(int unit) +{ + int i; + int found = 0; + + DBGL2(L2_PRIM, "DL-ESTABLISH-CONF", ("unit %d\n",unit)); + + for(i=0; i < N_CALL_DESC; i++) + { + if( (call_desc[i].cdid != 0) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + ctrl_desc[call_desc[i].controller].dl_est = DL_UP; + + DBGL3(L3_MSG, "i4b_dl_establish_cnf", ("unit=%d, index=%d cdid=%u cr=%d\n", + unit, i, call_desc[i].cdid, call_desc[i].cr)); + + next_l3state(&call_desc[i], EV_DLESTCF); + found++; + } + } + + if(found == 0) + { + DBGL3(L3_ERR, "i4b_dl_establish_cnf", ("ERROR, no cdid for unit %d found!\n", unit)); + return(-1); + } + else + { + return(0); + } +} + +/*---------------------------------------------------------------------------* + * DL RELEASE INDICATION from Layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_release_ind(int unit) +{ + int i; + int found = 0; + + DBGL2(L2_PRIM, "DL-RELEASE-IND", ("unit %d\n",unit)); + + /* first set controller to down */ + + for(i=0; i < nctrl; i++) + { + if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[i].unit == unit)) + { + DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d DL released!\n",unit)); + ctrl_desc[i].dl_est = DL_DOWN; + found = 1; + } + } + + if(found == 0) + { + DBGL3(L3_ERR, "i4b_dl_release_ind", ("ERROR, controller not found for unit=%d!\n",unit)); + return(-1); + } + + found = 0; + + /* second, inform all (!) active calls of the event */ + + for(i=0; i < N_CALL_DESC; i++) + { + if( (call_desc[i].cdid != 0) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + DBGL3(L3_MSG, "i4b_dl_release_ind", ("unit=%d, index=%d cdid=%u cr=%d\n", + unit, i, call_desc[i].cdid, call_desc[i].cr)); + next_l3state(&call_desc[i], EV_DLRELIN); + found++; + } + } + + if(found == 0) + { + /* this is not an error since it might be a normal call end */ + DBGL3(L3_MSG, "i4b_dl_release_ind", ("no cdid for unit %d found\n", unit)); + } + return(0); +} + +/*---------------------------------------------------------------------------* + * DL RELEASE CONFIRM from Layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_release_cnf(int unit) +{ + int i; + + DBGL2(L2_PRIM, "DL-RELEASE-CONF", ("unit %d\n",unit)); + + for(i=0; i < nctrl; i++) + { + if((ctrl_desc[i].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[i].unit == unit)) + { + DBGL3(L3_MSG, "i4b_dl_release_cnf", ("unit=%d DL released!\n",unit)); + ctrl_desc[i].dl_est = DL_DOWN; + return(0); + } + } + DBGL3(L3_ERR, "i4b_dl_release_cnf", ("ERROR, controller not found for unit=%d!\n",unit)); + return(-1); +} + +/*---------------------------------------------------------------------------* + * i4b_dl_data_ind - process a rx'd I-frame got from layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_data_ind(int unit, struct mbuf *m) +{ +#ifdef NOTDEF + DBGL2(L2_PRIM, "DL-DATA-IND", ("unit %d\n",unit)); +#endif + i4b_decode_q931(unit, m->m_len, m->m_data); + i4b_Dfreembuf(m); + return(0); +} + +/*---------------------------------------------------------------------------* + * dl_unit_data_ind - process a rx'd U-frame got from layer 2 + *---------------------------------------------------------------------------*/ +int +i4b_dl_unit_data_ind(int unit, struct mbuf *m) +{ +#ifdef NOTDEF + DBGL2(L2_PRIM, "DL-UNIT-DATA-IND", ("unit %d\n",unit)); +#endif + i4b_decode_q931(unit, m->m_len, m->m_data); + i4b_Dfreembuf(m); + return(0); +} + +/*---------------------------------------------------------------------------* + * send CONNECT message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_connect(call_desc_t *cd) +{ + struct mbuf *m; + u_char *ptr; + + DBGL3(L3_PRIM, "tx CONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_LEN)) == NULL) + panic("i4b_l3_tx_connect: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = CONNECT; /* message type = connect */ + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send RELEASE COMPLETE message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_release_complete(call_desc_t *cd, int send_cause_flag) +{ + struct mbuf *m; + u_char *ptr; + int len = I_FRAME_HDRLEN + MSG_RELEASE_COMPLETE_LEN; + + DBGL3(L3_PRIM, "tx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if(send_cause_flag == 0) + len -= 4; + + if((m = i4b_Dgetmbuf(len)) == NULL) + panic("i4b_l3_tx_release_complete: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = RELEASE_COMPLETE; /* message type = release complete */ + + if(send_cause_flag) + { + *ptr++ = IEI_CAUSE; /* cause ie */ + *ptr++ = CAUSE_LEN; + *ptr++ = CAUSE_STD_LOC_OUT; + *ptr++ = make_q931_cause(cd->cause_out); + } + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send DISCONNECT message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_disconnect(call_desc_t *cd) +{ + struct mbuf *m; + u_char *ptr; + + DBGL3(L3_PRIM, "tx DISCONNECT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_DISCONNECT_LEN)) == NULL) + panic("i4b_l3_tx_disconnect: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call ref length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = DISCONNECT; /* message type = disconnect */ + + *ptr++ = IEI_CAUSE; /* cause ie */ + *ptr++ = CAUSE_LEN; + *ptr++ = CAUSE_STD_LOC_OUT; + *ptr++ = make_q931_cause(cd->cause_out); + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send SETUP message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_setup(call_desc_t *cd) +{ + struct mbuf *m; + u_char *ptr; + int slen = strlen(cd->src_telno); + int dlen = strlen(cd->dst_telno); + + /* + * there is one additional octet if cd->bprot == BPROT_NONE + * NOTE: the selection of a bearer capability by a B L1 + * protocol is highly questionable and a better + * mechanism should be used in future. (-hm) + */ + + DBGL3(L3_PRIM, "tx SETUP", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_SETUP_LEN + slen + dlen + + (cd->bprot == BPROT_NONE ? 1 : 0))) == NULL) + { + panic("i4b_l3_tx_setup: can't allocate mbuf\n"); + } + + cd->crflag = CRF_ORIG; /* we are the originating side */ + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call ref length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = SETUP; /* message type = setup */ + + *ptr++ = IEI_SENDCOMPL; /* sending complete */ + + *ptr++ = IEI_BEARERCAP; /* bearer capability */ + + /* XXX + * currently i have no idea if this should be switched by + * the choosen B channel protocol or if there should be a + * separate configuration item for the bearer capability. + * For now, it is switched by the choosen b protocol (-hm) + */ + + switch(cd->bprot) + { + case BPROT_NONE: /* telephony */ + *ptr++ = IEI_BEARERCAP_LEN+1; + *ptr++ = IT_CAP_SPEECH; + *ptr++ = IT_RATE_64K; + *ptr++ = IT_UL1_G711A; + break; + + case BPROT_RHDLC: /* raw HDLC */ + *ptr++ = IEI_BEARERCAP_LEN; + *ptr++ = IT_CAP_UNR_DIG_INFO; + *ptr++ = IT_RATE_64K; + break; + + default: + *ptr++ = IEI_BEARERCAP_LEN; + *ptr++ = IT_CAP_UNR_DIG_INFO; + *ptr++ = IT_RATE_64K; + break; + } + + *ptr++ = IEI_CHANNELID; /* channel id */ + *ptr++ = IEI_CHANNELID_LEN; /* channel id length */ + + switch(cd->channelid) + { + case CHAN_B1: + *ptr++ = CHANNELID_B1; + break; + case CHAN_B2: + *ptr++ = CHANNELID_B2; + break; + default: + *ptr++ = CHANNELID_ANY; + break; + } + + *ptr++ = IEI_CALLINGPN; /* calling party no */ + *ptr++ = IEI_CALLINGPN_LEN+slen;/* calling party no length */ + *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */ + strncpy(ptr, cd->src_telno, slen); + ptr += slen; + + *ptr++ = IEI_CALLEDPN; /* called party no */ + *ptr++ = IEI_CALLEDPN_LEN+dlen; /* called party no length */ + *ptr++ = NUMBER_TYPEPLAN; /* type of number, number plan id */ + strncpy(ptr, cd->dst_telno, dlen); + ptr += dlen; + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send CONNECT ACKNOWLEDGE message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_connect_ack(call_desc_t *cd) +{ + struct mbuf *m; + u_char *ptr; + + DBGL3(L3_PRIM, "tx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_CONNECT_ACK_LEN)) == NULL) + panic("i4b_l3_tx_connect_ack: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = CONNECT_ACKNOWLEDGE; /* message type = connect ack */ + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send STATUS message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_status(call_desc_t *cd, u_char q850cause) +{ + struct mbuf *m; + u_char *ptr; + + DBGL3(L3_PRIM, "tx STATUS", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_STATUS_LEN)) == NULL) + panic("i4b_l3_tx_status: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = STATUS; /* message type = connect ack */ + + *ptr++ = IEI_CAUSE; /* cause ie */ + *ptr++ = CAUSE_LEN; + *ptr++ = CAUSE_STD_LOC_OUT; + *ptr++ = q850cause; + + *ptr++ = IEI_CALLSTATE; /* call state ie */ + *ptr++ = CALLSTATE_LEN; + *ptr++ = i4b_status_tab[cd->Q931state]; + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send RELEASE message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_release(call_desc_t *cd, int send_cause_flag) +{ + struct mbuf *m; + u_char *ptr; + int len = I_FRAME_HDRLEN + MSG_RELEASE_LEN; + + DBGL3(L3_PRIM, "tx RELEASE", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + if(send_cause_flag == 0) + len -= 4; + + if((m = i4b_Dgetmbuf(len)) == NULL) + panic("i4b_l3_tx_release: can't allocate mbuf\n"); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = RELEASE; /* message type = release complete */ + + if(send_cause_flag) + { + *ptr++ = IEI_CAUSE; /* cause ie */ + *ptr++ = CAUSE_LEN; + *ptr++ = CAUSE_STD_LOC_OUT; + *ptr++ = make_q931_cause(cd->cause_out); + } + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +/*---------------------------------------------------------------------------* + * send ALERTING message + *---------------------------------------------------------------------------*/ +void +i4b_l3_tx_alert(call_desc_t *cd) +{ + struct mbuf *m; + u_char *ptr; + + if((m = i4b_Dgetmbuf(I_FRAME_HDRLEN + MSG_ALERT_LEN)) == NULL) + panic("i4b_l3_tx_alert: can't allocate mbuf\n"); + + DBGL3(L3_PRIM, "tx ALERT", ("unit %d, cr = 0x%02x\n", ctrl_desc[cd->controller].unit, cd->cr)); + + ptr = m->m_data + I_FRAME_HDRLEN; + + *ptr++ = PD_Q931; /* protocol discriminator */ + *ptr++ = 0x01; /* call reference length */ + *ptr++ = setup_cr(cd, cd->cr); /* call reference value */ + *ptr++ = ALERT; /* message type = alert */ + + DL_Data_Req(ctrl_desc[cd->controller].unit, m); +} + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer3/i4b_l3.h b/sys/i4b/layer3/i4b_l3.h new file mode 100644 index 0000000..9d05055 --- /dev/null +++ b/sys/i4b/layer3/i4b_l3.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l3.h - layer 3 header file + * ------------------------------ + * + * $Id: i4b_l3.h,v 1.8 1998/12/05 18:05:30 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:31:41 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L3_H_ +#define _I4B_L3_H_ + +extern int utoc_tab[]; +extern unsigned char cause_tab_q931[]; + +extern int i4b_aoc ( unsigned char *, call_desc_t *cd ); +extern void i4b_decode_q931 ( int unit, int msg_len, u_char *msg_ptr ); +extern int i4b_decode_q931_cs0_ie ( int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr ); +extern void i4b_decode_q931_message ( int unit, call_desc_t *cd, u_char message_type ); +extern void i4b_l3_stop_all_timers ( call_desc_t *cd ); +extern void i4b_l3_tx_alert ( call_desc_t *cd ); +extern void i4b_l3_tx_connect ( call_desc_t *cd ); +extern void i4b_l3_tx_connect_ack ( call_desc_t *cd ); +extern void i4b_l3_tx_disconnect ( call_desc_t *cd ); +extern void i4b_l3_tx_release ( call_desc_t *cd, int send_cause_flag ); +extern void i4b_l3_tx_release_complete ( call_desc_t *cd, int send_cause_flag ); +extern void i4b_l3_tx_setup ( call_desc_t *cd ); +extern void i4b_l3_tx_status ( call_desc_t *cd, u_char q850cause ); +extern int i4b_dl_data_ind ( int unit, struct mbuf *m ); +extern int i4b_dl_establish_cnf ( int unit ); +extern int i4b_dl_establish_ind ( int unit ); +extern int i4b_dl_release_cnf ( int unit ); +extern int i4b_dl_release_ind ( int unit ); +extern int i4b_dl_unit_data_ind ( int unit, struct mbuf *m ); +extern int i4b_get_dl_stat( call_desc_t *cd ); +extern int i4b_mdl_status_ind ( int unit, int status, int parm); +extern void i4b_print_frame ( int len, u_char *buf ); +extern void next_l3state ( call_desc_t *cd, int event ); +extern char *print_l3state ( call_desc_t *cd ); +extern unsigned char setup_cr ( call_desc_t *cd, unsigned char cr ); +extern void T303_start ( call_desc_t *cd ); +extern void T303_stop ( call_desc_t *cd ); +extern void T305_start ( call_desc_t *cd ); +extern void T305_stop ( call_desc_t *cd ); +extern void T308_start ( call_desc_t *cd ); +extern void T308_stop ( call_desc_t *cd ); +extern void T309_start ( call_desc_t *cd ); +extern void T309_stop ( call_desc_t *cd ); +extern void T310_start ( call_desc_t *cd ); +extern void T310_stop ( call_desc_t *cd ); +extern void T313_start ( call_desc_t *cd ); +extern void T313_stop ( call_desc_t *cd ); + +#endif /* _I4B_L3_H_ */ diff --git a/sys/i4b/layer3/i4b_l3fsm.c b/sys/i4b/layer3/i4b_l3fsm.c new file mode 100644 index 0000000..e45e119 --- /dev/null +++ b/sys/i4b/layer3/i4b_l3fsm.c @@ -0,0 +1,1034 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l3fsm.c - layer 3 FSM + * ------------------------- + * + * $Id: i4b_l3fsm.c,v 1.13 1998/12/05 18:05:31 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:32:17 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> + +#include <i4b/layer4/i4b_l4.h> + + +static void F_00A(call_desc_t *cd), F_00H(call_desc_t *cd), F_00I(call_desc_t *cd); +static void F_00J(call_desc_t *cd); + +static void F_01B(call_desc_t *cd), F_01K(call_desc_t *cd), F_01L(call_desc_t *cd); +static void F_01M(call_desc_t *cd), F_01N(call_desc_t *cd), F_01U(call_desc_t *cd); +static void F_01O(call_desc_t *cd); + +static void F_03C(call_desc_t *cd), F_03N(call_desc_t *cd), F_03O(call_desc_t *cd); +static void F_03P(call_desc_t *cd), F_03Y(call_desc_t *cd); + +static void F_04O(call_desc_t *cd); + +static void F_06D(call_desc_t *cd), F_06E(call_desc_t *cd), F_06F(call_desc_t *cd); +static void F_06G(call_desc_t *cd), F_06J(call_desc_t *cd), F_06Q(call_desc_t *cd); + +static void F_07E(call_desc_t *cd), F_07F(call_desc_t *cd), F_07G(call_desc_t *cd); + +static void F_08R(call_desc_t *cd), F_08Z(call_desc_t *cd); + +static void F_09D(call_desc_t *cd), F_09E(call_desc_t *cd), F_09F(call_desc_t *cd); +static void F_09G(call_desc_t *cd); + +static void F_11J(call_desc_t *cd), F_11Q(call_desc_t *cd), F_11V(call_desc_t *cd); + +static void F_12C(call_desc_t *cd), F_12J(call_desc_t *cd); + +static void F_19I(call_desc_t *cd), F_19J(call_desc_t *cd), F_19K(call_desc_t *cd); +static void F_19W(call_desc_t *cd); + +static void F_NCNA(call_desc_t *cd), F_STENQ(call_desc_t *cd), F_STAT(call_desc_t *cd); +static void F_INFO(call_desc_t *cd), F_RELCP(call_desc_t *cd), F_REL(call_desc_t *cd); +static void F_DISC(call_desc_t *cd), F_DCRQ(call_desc_t *cd), F_UEM(call_desc_t *cd); +static void F_SIGN(call_desc_t *cd), F_DLEI(call_desc_t *cd), F_ILL(call_desc_t *cd); +static void F_309TO(call_desc_t *cd), F_DECF(call_desc_t *cd), F_FCTY(call_desc_t *cd); +static void F_DECF1(call_desc_t *cd), F_DECF2(call_desc_t *cd), F_DECF3(call_desc_t *cd); +static void F_DLRI(call_desc_t *cd), F_DLRIA(call_desc_t *cd), F_DECF4(call_desc_t *cd); + +static char *l3state_text[N_STATES] = { + "ST_U0 - Null", + "ST_U1 - Out Init", + "ST_U3 - Out Proc", + "ST_U4 - Out Delv", + "ST_U6 - In Pres", + "ST_U7 - In Rxd", + "ST_U8 - In ConReq", + "ST_U9 - In Proc", + "ST_U10 - Active", + "ST_U11 - Disc Req", + "ST_U12 - Disc Ind", + "ST_U19 - Rel Req", + + "ST_IWA - In Wait EST-Accept", + "ST_IWR - In Wait EST-Reject", + "ST_OW - Out Wait EST", + "ST_IWL - In Wait EST-Alert", + + "ST_SUSE - Subroutine sets state", + + "Illegal State" +}; + +static char *l3event_text[N_EVENTS] = { + "EV_SETUPRQ - L4 SETUP REQ", /* setup request from L4 */ + "EV_DISCRQ - L4 DISC REQ", /* disconnect request from L4 */ + "EV_RELRQ - L4 REL REQ", /* release request from L4 */ + "EV_ALERTRQ - L4 ALERT REQ", /* alerting request from L4 */ + "EV_SETACRS - L4 accept RSP", /* setup response accept from l4 */ + "EV_SETRJRS - L4 reject RSP", /* setup response reject from l4 */ + "EV_SETDCRS - L4 ignore RSP", /* setup response dontcare from l4 */ + + "EV_SETUP - rxd SETUP", /* incoming SETUP message from L2 */ + "EV_STATUS - rxd STATUS", /* incoming STATUS message from L2 */ + "EV_RELEASE - rxd REL", /* incoming RELEASE message from L2 */ + "EV_RELCOMP - rxd REL COMPL", /* incoming RELEASE COMPLETE from L2 */ + "EV_SETUPAK - rxd SETUP ACK", /* incoming SETUP ACK message from L2 */ + "EV_CALLPRC - rxd CALL PROC", /* incoming CALL PROCEEDING from L2 */ + "EV_ALERT - rxd ALERT", /* incoming ALERT message from L2 */ + "EV_CONNECT - rxd CONNECT", /* incoming CONNECT message from L2 */ + "EV_PROGIND - rxd PROG IND", /* incoming Progress IND from L2 */ + "EV_DISCONN - rxd DISC", /* incoming DISCONNECT message from L2 */ + "EV_CONACK - rxd CONN ACK", /* incoming CONNECT ACK message from L2 */ + "EV_STATENQ - rxd STAT ENQ", /* incoming STATUS ENQ message from L2 */ + "EV_INFO - rxd INFO", /* incoming INFO message from L2 */ + "EV_FACILITY - rxd FACILITY", /* incoming FACILITY message */ + + "EV_T303EXP - T303 timeout", /* Timer T303 expired */ + "EV_T305EXP - T305 timeout", /* Timer T305 expired */ + "EV_T308EXP - T308 timeout", /* Timer T308 expired */ + "EV_T309EXP - T309 timeout", /* Timer T309 expired */ + "EV_T310EXP - T310 timeout", /* Timer T310 expired */ + "EV_T313EXP - T313 timeout", /* Timer T313 expired */ + + "EV_DLESTIN - L2 DL_Est_Ind", /* dl establish indication from l2 */ + "EV_DLRELIN - L2 DL_Rel_Ind", /* dl release indication from l2 */ + "EV_DLESTCF - L2 DL_Est_Cnf", /* dl establish confirm from l2 */ + "EV_DLRELCF - L2 DL_Rel_Cnf", /* dl release confirm from l2 */ + + "EV_ILL - Illegal event!!" /* Illegal */ +}; + +/*---------------------------------------------------------------------------* + * layer 3 state transition table + *---------------------------------------------------------------------------*/ +struct l3state_tab { + void (*func) (call_desc_t *); /* function to execute */ + int newstate; /* next state */ +} l3state_tab[N_EVENTS][N_STATES] = { + +/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */ +/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*EV_SETUPRQ*/ {{F_00A, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_DISCRQ */ {{F_ILL, ST_ILL}, {F_01B, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_NCNA, ST_U12}, {F_ILL, ST_ILL}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_DCRQ, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_RELRQ */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_12C, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_ALERTRQ*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06D, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_09D, ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_SETACRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06E, ST_SUSE}, {F_07E, ST_U8}, {F_ILL, ST_ILL}, {F_09E, ST_U8}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_SETRJRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06F, ST_SUSE}, {F_07F, ST_U0}, {F_ILL, ST_ILL}, {F_09F, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_SETDCRS*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_06G, ST_U0}, {F_07G, ST_U0}, {F_ILL, ST_ILL}, {F_09G, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */ +/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*EV_SETUP */ {{F_00H, ST_U6}, {F_SIGN, ST_U1}, {F_SIGN, ST_U3}, {F_SIGN, ST_U4}, {F_SIGN, ST_U6}, {F_SIGN, ST_U7}, {F_SIGN, ST_U8}, {F_SIGN, ST_U9}, {F_SIGN, ST_U10}, {F_SIGN, ST_U11}, {F_SIGN, ST_U12}, {F_SIGN, ST_U19}, {F_SIGN, ST_IWA}, {F_SIGN, ST_IWR}, {F_SIGN, ST_OW}, {F_SIGN, ST_IWL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_STATUS */ {{F_00I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_19I, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_STAT, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_RELEASE*/ {{F_00J, ST_U0}, {F_UEM, ST_SUSE}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_06J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_11J, ST_U0}, {F_12J, ST_U0}, {F_19J, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_REL, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_RELCOMP*/ {{F_NCNA, ST_U0}, {F_01K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_19K, ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_RELCP,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_SETUPAK*/ {{F_UEM, ST_SUSE}, {F_01L, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_CALLPRC*/ {{F_UEM, ST_SUSE}, {F_01M, ST_U3}, {F_NCNA, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_ALERT */ {{F_UEM, ST_SUSE}, {F_01N, ST_U4}, {F_03N, ST_U4}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_CONNECT*/ {{F_UEM, ST_SUSE}, {F_01O, ST_U10}, {F_03O, ST_U10}, {F_04O, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_PROGIND*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_03P, ST_U3}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_DISCONN*/ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_06Q, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_11Q, ST_U19}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_DISC, ST_U12}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_CONACK */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_08R, ST_U10}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_STATENQ*/ {{F_STENQ,ST_U0}, {F_STENQ,ST_U1}, {F_STENQ,ST_U3}, {F_STENQ,ST_U4}, {F_STENQ,ST_U6}, {F_STENQ,ST_U7}, {F_STENQ,ST_U8}, {F_STENQ,ST_U9}, {F_STENQ,ST_U10}, {F_STENQ,ST_U11}, {F_STENQ,ST_U12}, {F_STENQ,ST_U19}, {F_STENQ,ST_IWA}, {F_STENQ,ST_IWR}, {F_STENQ,ST_OW}, {F_STENQ,ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_INFO */ {{F_UEM, ST_SUSE}, {F_UEM, ST_SUSE}, {F_INFO, ST_U3}, {F_INFO, ST_U4}, {F_UEM, ST_SUSE}, {F_INFO, ST_U7}, {F_INFO, ST_U8}, {F_INFO, ST_U9}, {F_INFO, ST_U10}, {F_INFO, ST_U11}, {F_INFO, ST_U12}, {F_UEM, ST_SUSE}, {F_INFO, ST_IWA}, {F_INFO, ST_IWR}, {F_INFO, ST_OW}, {F_INFO, ST_OW}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_FACILITY*/ {{F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_FCTY, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */ +/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*EV_T303EXP*/ {{F_ILL, ST_ILL}, {F_01U, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_T305EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_11V, ST_U19}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_T308EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_19W, ST_SUSE}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_T309EXP*/ {{F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_309TO,ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_T310EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_03Y, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_T313EXP*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_08Z, ST_U11}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/* STATE: ST_U0 ST_U1 ST_U3 ST_U4 ST_U6 ST_U7 ST_U8 ST_U9 ST_U10 ST_U11 ST_U12 ST_U19 ST_IWA ST_IWR ST_OW ST_IWL ST_SUBSET ST_ILL */ +/* ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/*EV_DLESTIN*/ {{F_ILL, ST_ILL}, {F_DLEI, ST_U1}, {F_DLEI, ST_U3}, {F_DLEI, ST_U4}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_DLEI, ST_U1}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_DLRELIN*/ {{F_NCNA, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRIA,ST_U10}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_DLRI, ST_U0}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_DLESTCF*/ {{F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF, ST_SUSE}, {F_DECF2,ST_U8}, {F_DECF3,ST_U0}, {F_DECF1,ST_U1}, {F_DECF4,ST_U7}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_DLRELCF*/ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}}, +/*EV_ILL */ {{F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}, {F_ILL, ST_ILL}} +}; + +/*---------------------------------------------------------------------------* + * event handler + *---------------------------------------------------------------------------*/ +void next_l3state(call_desc_t *cd, int event) +{ + int currstate, newstate; + + if(event > N_EVENTS) + panic("i4b_l3fsm.c: event > N_EVENTS\n"); + + currstate = cd->Q931state; + + if(currstate > N_STATES) + panic("i4b_l3fsm.c: currstate > N_STATES\n"); + + newstate = l3state_tab[event][currstate].newstate; + + if(newstate > N_STATES) + panic("i4b_l3fsm.c: newstate > N_STATES\n"); + + DBGL3(L3_F_MSG, "next_l3state", ("L3 FSM event [%s]: [%s => %s]\n", + l3event_text[event], + l3state_text[currstate], + l3state_text[newstate])); + + /* execute function */ + + (*l3state_tab[event][currstate].func)(cd); + + if(newstate == ST_ILL) + { + newstate = currstate; + DBGL3(L3_F_ERR, "next_l3state", ("FSM illegal state, state = %s, event = %s!\n", + l3state_text[newstate], + l3event_text[event])); + } + + if(newstate != ST_SUSE) + cd->Q931state = newstate; +} + +/*---------------------------------------------------------------------------* + * resturn pointer to current state description + *---------------------------------------------------------------------------*/ +char *print_l3state(call_desc_t *cd) +{ + return((char *) l3state_text[cd->Q931state]); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U0 event L4 setup req + *---------------------------------------------------------------------------*/ +static void F_00A(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_00A", ("FSM function F_00A executing\n")); + + if(i4b_get_dl_stat(cd) == DL_DOWN) + { + DL_Est_Req(ctrl_desc[cd->controller].unit); + cd->Q931state = ST_OW; + } + else + { + i4b_l3_tx_setup(cd); + cd->Q931state = ST_U1; + } + + cd->T303_first_to = 1; + T303_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U0 event SETUP from L2 + *---------------------------------------------------------------------------*/ +static void F_00H(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_00H", ("FSM function F_00H executing\n")); + i4b_l4_connect_ind(cd); /* tell l4 we have an incoming setup */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U0 event STATUS from L2 + *---------------------------------------------------------------------------*/ +static void F_00I(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_00I", ("FSM function F_00I executing\n")); + + if(cd->call_state != 0) + { + cd->cause_out = 101; + i4b_l3_tx_release_complete(cd, 1); /* 1 = send cause */ + } + cd->Q931state = ST_U0; +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U0 event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_00J(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_00J", ("FSM function F_00J executing\n")); + i4b_l3_tx_release_complete(cd, 0); /* 0 = don't send cause */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event disconnect req from L4 + *---------------------------------------------------------------------------*/ +static void F_01B(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01B", ("FSM function F_01B executing\n")); + /* cause from L4 */ + i4b_l3_tx_disconnect(cd); + T303_stop(cd); + T305_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event RELEASE COMPLETE from L2 + *---------------------------------------------------------------------------*/ +static void F_01K(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01K", ("FSM function F_01K executing\n")); + T303_stop(cd); + i4b_l4_disconnect_ind(cd); /* tell l4 we were rejected */ + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event SETUP ACK from L2 + *---------------------------------------------------------------------------*/ +static void F_01L(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01L", ("FSM function F_01L executing\n")); + T303_stop(cd); + + /* + * since this implementation does NOT support overlap sending, + * we react here as if we received a CALL PROCEEDING because + * several PBX's react with a SETUP ACK even if the called + * number is complete AND we sent a SENDING COMPLETE in the + * preceeding SETUP message. (-hm) + */ + + T310_start(cd); + i4b_l4_proceeding_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event CALL PROCEEDING from L2 + *---------------------------------------------------------------------------*/ +static void F_01M(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01M", ("FSM function F_01M executing\n")); + T303_stop(cd); + T310_start(cd); + i4b_l4_proceeding_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event ALERT from L2 (XXX !) + *---------------------------------------------------------------------------*/ +static void F_01N(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01N", ("FSM function F_01N executing\n")); + T303_stop(cd); + i4b_l4_alert_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event CONNECT from L2 (XXX !) + *---------------------------------------------------------------------------*/ +static void F_01O(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01O", ("FSM function F_01O executing\n")); + T303_stop(cd); + i4b_l3_tx_connect_ack(cd); + i4b_l4_connect_active_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U1 event T303 timeout + *---------------------------------------------------------------------------*/ +static void F_01U(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_01U", ("FSM function F_01U executing\n")); + if(cd->T303_first_to == 1) + { + cd->T303_first_to = 0; + i4b_l3_tx_setup(cd); + T303_start(cd); + cd->Q931state = ST_U1; + } + else + { + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); + cd->Q931state = ST_U0; + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U3 event release req from L4 + *---------------------------------------------------------------------------*/ +static void F_03C(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_03C", ("FSM function F_03C executing\n")); + T310_stop(cd); + cd->cause_out = 6; + i4b_l3_tx_release(cd, 1); /* 0 = don't send cause */ + cd->T308_first_to = 1; + T308_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U3 event ALERT from L2 + *---------------------------------------------------------------------------*/ +static void F_03N(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_03N", ("FSM function F_03N executing\n")); + T310_stop(cd); + i4b_l4_alert_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U3 event CONNECT from L2 + *---------------------------------------------------------------------------*/ +static void F_03O(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_03O", ("FSM function F_03O executing\n")); + T310_stop(cd); + i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */ + i4b_l4_connect_active_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U3 event PROGESS IND from L2 + *---------------------------------------------------------------------------*/ +static void F_03P(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_03P", ("FSM function F_03P executing\n")); + T310_stop(cd); +#ifdef NOTDEF + i4b_l4_progress_ind(cd); +#endif +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U3 event T310 timeout + *---------------------------------------------------------------------------*/ +static void F_03Y(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_03Y", ("FSM function F_03Y executing\n")); + cd->cause_out = 102; /* recovery on timer expiry */ + i4b_l3_tx_disconnect(cd); + T305_start(cd); + i4b_l4_disconnect_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U4 event CONNECT from L2 + *---------------------------------------------------------------------------*/ +static void F_04O(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_04O", ("FSM function F_04O executing\n")); + i4b_l3_tx_connect_ack(cd); /* CONNECT ACK to network */ + i4b_l4_connect_active_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event alert req from L4 + *---------------------------------------------------------------------------*/ +static void F_06D(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06D", ("FSM function F_06D executing\n")); + + if(i4b_get_dl_stat(cd) == DL_DOWN) + { + DL_Est_Req(ctrl_desc[cd->controller].unit); + cd->Q931state = ST_IWL; + } + else + { + i4b_l3_tx_alert(cd); + cd->Q931state = ST_U7; + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event incoming setup accept from L4 + *---------------------------------------------------------------------------*/ +static void F_06E(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06E", ("FSM function F_06E executing\n")); + + if(i4b_get_dl_stat(cd) == DL_DOWN) + { + DL_Est_Req(ctrl_desc[cd->controller].unit); + cd->Q931state = ST_IWA; + } + else + { + i4b_l3_tx_connect(cd); + cd->Q931state = ST_U8; + } + T313_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event incoming setup reject from L4 + *---------------------------------------------------------------------------*/ +static void F_06F(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06F", ("FSM function F_06F executing\n")); + + if(i4b_get_dl_stat(cd) == DL_DOWN) + { + DL_Est_Req(ctrl_desc[cd->controller].unit); + cd->Q931state = ST_IWR; + } + else + { + int s = SPLI4B(); + i4b_l3_tx_release_complete(cd, 1); + cd->Q931state = ST_U0; + freecd_by_cd(cd); + splx(s); + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event incoming setup ignore from L4 + *---------------------------------------------------------------------------*/ +static void F_06G(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06G", ("FSM function F_06G executing\n")); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_06J(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06J", ("FSM function F_06J executing\n")); + i4b_l3_tx_release_complete(cd, 0); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U6 event DISCONNECT from L2 + *---------------------------------------------------------------------------*/ +static void F_06Q(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_06Q", ("FSM function F_06Q executing\n")); + i4b_l4_disconnect_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U7 event setup response accept from L4 + *---------------------------------------------------------------------------*/ +static void F_07E(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_07E", ("FSM function F_07E executing\n")); + i4b_l3_tx_connect(cd); + T313_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U7 event setup response reject from L4 + *---------------------------------------------------------------------------*/ +static void F_07F(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_07F", ("FSM function F_07F executing\n")); + i4b_l3_tx_release_complete(cd, 1); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U7 event setup response ignore from L4 + *---------------------------------------------------------------------------*/ +static void F_07G(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_07G", ("FSM function F_07G executing\n")); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U8 event CONNECT ACK from L2 + *---------------------------------------------------------------------------*/ +static void F_08R(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_08R", ("FSM function F_08R executing\n")); + T313_stop(cd); + i4b_l4_connect_active_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U8 event T313 timeout + *---------------------------------------------------------------------------*/ +static void F_08Z(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_08Z", ("FSM function F_08Z executing\n")); + cd->cause_out = 102; /* recovery on timer expiry */ + i4b_l3_tx_disconnect(cd); + T305_start(cd); + i4b_l4_disconnect_ind(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U9 event alert req from L4 + *---------------------------------------------------------------------------*/ +static void F_09D(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_09D", ("FSM function F_09D executing\n")); + i4b_l3_tx_alert(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U9 event setup response accept from L4 + *---------------------------------------------------------------------------*/ +static void F_09E(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_09E", ("FSM function F_09E executing\n")); + i4b_l3_tx_connect(cd); + T313_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U9 event setup response reject from L4 + *---------------------------------------------------------------------------*/ +static void F_09F(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_09F", ("FSM function F_09F executing\n")); + i4b_l3_tx_release_complete(cd, 1); + freecd_by_cd(cd); +} +/*---------------------------------------------------------------------------* + * L3 FSM state U9 event setup response ignore from L4 + *---------------------------------------------------------------------------*/ +static void F_09G(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_09G", ("FSM function F_09G executing\n")); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U11 event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_11J(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_11J", ("FSM function F_11J executing\n")); + T305_stop(cd); + i4b_l3_tx_release_complete(cd, 0); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U11 event DISCONNECT from L2 + *---------------------------------------------------------------------------*/ +static void F_11Q(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_11Q", ("FSM function F_11Q executing\n")); + T305_stop(cd); + i4b_l3_tx_release(cd, 0); + cd->T308_first_to = 1; + T308_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U11 event T305 timeout + *---------------------------------------------------------------------------*/ +static void F_11V(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_11V", ("FSM function F_11V executing\n")); + cd->cause_out = 102; + i4b_l3_tx_release(cd, 1); + cd->T308_first_to = 1; + T308_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U12 event release req from L4 + *---------------------------------------------------------------------------*/ +static void F_12C(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_12C", ("FSM function F_12C executing\n")); + i4b_l3_tx_release(cd, 1); + cd->T308_first_to = 1; + T308_start(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U12 event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_12J(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_12J", ("FSM function F_12J executing\n")); + i4b_l3_tx_release_complete(cd, 0); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U19 event STATUS from L2 + *---------------------------------------------------------------------------*/ +static void F_19I(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_19I", ("FSM function F_19I executing\n")); + + if(cd->call_state == 0) + { + i4b_l4_status_ind(cd); + freecd_by_cd(cd); + cd->Q931state = ST_U0; + } + else + { + cd->Q931state = ST_U19; + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U19 event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_19J(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_19J", ("FSM function F_19J executing\n")); + T308_stop(cd); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U19 event RELEASE COMPLETE from L2 + *---------------------------------------------------------------------------*/ +static void F_19K(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_19K", ("FSM function F_19K executing\n")); + T308_stop(cd); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U19 event T308 timeout + *---------------------------------------------------------------------------*/ +static void F_19W(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_19W", ("FSM function F_19W executing\n")); + if(cd->T308_first_to == 0) + { + cd->T308_first_to = 1; + i4b_l3_tx_release(cd, 0); + T308_start(cd); + cd->Q931state = ST_U19; + } + else + { + cd->T308_first_to = 0; + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); + cd->Q931state = ST_U0; + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM routine no change no action + *---------------------------------------------------------------------------*/ +static void F_NCNA(call_desc_t *cd) +{ +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state event STATUS ENQ from L2 + *---------------------------------------------------------------------------*/ +static void F_STENQ(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_STENQ", ("FSM function F_STENQ executing\n")); + i4b_l3_tx_status(cd, CAUSE_Q850_STENQRSP); /* 30, resonse to stat enq */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state except 0 & 19 event STATUS from L2 + *---------------------------------------------------------------------------*/ +static void F_STAT(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_STAT", ("FSM function F_STAT executing\n")); + if(cd->call_state == 0) + { + i4b_l4_status_ind(cd); + cd->Q931state = ST_U0; + freecd_by_cd(cd); + } + else + { + /* XXX !!!!!!!!!!!!!!!!!! */ + + i4b_l4_status_ind(cd); + cd->cause_out = 101; /* message not compatible with call state */ + i4b_l3_tx_disconnect(cd); + T305_start(cd); + cd->Q931state = ST_U11; + } +} + +/*---------------------------------------------------------------------------* + * L3 FSM some states event INFORMATION from L2 + *---------------------------------------------------------------------------*/ +static void F_INFO(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_INFO", ("FSM function F_INFO executing\n")); + i4b_l4_info_ind(cd); + /* remain in current state */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM some states event RELEASE COMPLETE from L2 + *---------------------------------------------------------------------------*/ +static void F_RELCP(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_RELCP", ("FSM function F_RELCP executing\n")); + i4b_l3_stop_all_timers(cd); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM some states event RELEASE from L2 + *---------------------------------------------------------------------------*/ +static void F_REL(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_REL", ("FSM function F_REL executing\n")); + i4b_l3_stop_all_timers(cd); + i4b_l3_tx_release_complete(cd, 0); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM some states event DISCONNECT from L2 + *---------------------------------------------------------------------------*/ +static void F_DISC(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DISC", ("FSM function F_DISC executing\n")); + i4b_l3_stop_all_timers(cd); + + /* + * no disconnect ind to L4, no jump to state U12 + * instead we issue a RELEASE and jump to U19 + */ + + i4b_l3_tx_release(cd, 0); + cd->T308_first_to = 1; + T308_start(cd); + cd->Q931state = ST_U19; +} + +/*---------------------------------------------------------------------------* + * L3 FSM some states event disconnect request from L4 + *---------------------------------------------------------------------------*/ +static void F_DCRQ(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DCRQ", ("FSM function F_DCRQ executing\n")); + /* cause from L4 */ + i4b_l3_tx_disconnect(cd); + T305_start(cd); + cd->Q931state = ST_U11; +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state except 0 event unexpected message from L2 + *---------------------------------------------------------------------------*/ +static void F_UEM(call_desc_t *cd) +{ + DBGL3(L3_F_ERR, "F_UEM", ("FSM function F_UEM executing, state = %s\n", print_l3state(cd))); + i4b_l3_tx_status(cd, CAUSE_Q850_MSGNCWCS); /* 101, message not compatible with call state */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state except 0 event SETUP from L2 + *---------------------------------------------------------------------------*/ +static void F_SIGN(call_desc_t *cd) +{ + DBGL3(L3_F_ERR, "F_SIGN", ("FSM function F_SIGN executing\n")); + +/* XXX */ /* freecd_by_cd(cd); ?????????? XXX */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM relevant states event DL ESTABLISH IND from L2 + *---------------------------------------------------------------------------*/ +static void F_DLEI(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DLEI", ("FSM function F_DLEI executing\n")); + +/* XXX */ + + /* remain in current state */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state event illegal event occured + *---------------------------------------------------------------------------*/ +static void F_ILL(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_ILL", ("FSM function F_ILL executing\n")); +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state event T309 timeout + *---------------------------------------------------------------------------*/ +static void F_309TO(call_desc_t *cd) +{ + DBGL3(L3_F_ERR, "F_309TO", ("FSM function F_309TO executing\n")); + +/* XXX */ + +#ifdef NOTDEF + i4b_l4_dl_fail_ind(cd); +#endif + + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state event FACILITY message received + *---------------------------------------------------------------------------*/ +static void F_FCTY(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_FCTY", ("FSM function F_FCTY executing\n")); + /* ST_SUSE, no change in state ! */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM state ST_OW event DL ESTABLISH CONF from L2 + *---------------------------------------------------------------------------*/ +static void F_DECF1(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DECF1", ("FSM function F_DECF1 executing\n")); + i4b_l3_tx_setup(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state ST_IWA event DL ESTABLISH CONF from L2 + *---------------------------------------------------------------------------*/ +static void F_DECF2(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DECF2", ("FSM function F_DECF2 executing\n")); + i4b_l3_tx_connect(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state ST_IWR event DL ESTABLISH CONF from L2 + *---------------------------------------------------------------------------*/ +static void F_DECF3(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DECF3", ("FSM function F_DECF3 executing\n")); + i4b_l3_tx_release_complete(cd, 1); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state ST_IWL event DL ESTABLISH CONF from L2 + *---------------------------------------------------------------------------*/ +static void F_DECF4(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DECF4", ("FSM function F_DECF4 executing\n")); + i4b_l3_tx_alert(cd); +} + + +/*---------------------------------------------------------------------------* + * L3 FSM any state event DL ESTABLISH CONF from L2 + *---------------------------------------------------------------------------*/ +static void F_DECF(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DECF", ("FSM function F_DECF executing\n")); + T309_stop(cd); + i4b_l3_tx_status(cd, CAUSE_Q850_NORMUNSP); /* 31, normal unspecified */ +} + +/*---------------------------------------------------------------------------* + * L3 FSM any state except U10 event DL RELEASE IND from L2 + *---------------------------------------------------------------------------*/ +static void F_DLRI(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DLRI", ("FSM function F_DLRI executing\n")); + i4b_l3_stop_all_timers(cd); + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); +} + +/*---------------------------------------------------------------------------* + * L3 FSM state U10 event DL RELEASE IND from L2 + *---------------------------------------------------------------------------*/ +static void F_DLRIA(call_desc_t *cd) +{ + DBGL3(L3_F_MSG, "F_DLRIA", ("FSM function F_DLRIA executing\n")); + + if(cd->T309 == TIMER_IDLE) + T309_start(cd); + + DL_Est_Req(ctrl_desc[cd->controller].unit); +} + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer3/i4b_l3fsm.h b/sys/i4b/layer3/i4b_l3fsm.h new file mode 100644 index 0000000..d69b810 --- /dev/null +++ b/sys/i4b/layer3/i4b_l3fsm.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l3fsm.c - layer 3 FSM + * ------------------------- + * + * $Id: i4b_l3fsm.h,v 1.5 1998/12/05 18:05:33 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:32:45 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L3FSM_H_ +#define _I4B_L3FSM_H_ + +enum Q931_states { + ST_U0, + ST_U1, + ST_U3, + ST_U4, + ST_U6, + ST_U7, + ST_U8, + ST_U9, + ST_U10, + ST_U11, + ST_U12, + ST_U19, + + ST_IWA, /* incoming call, wait establish, then accept */ + ST_IWR, /* incoming call, wait establish, then reject */ + ST_OW, /* outgoing call, wait establish */ + ST_IWL, /* incoming call, wait establish, then alert */ + + ST_SUSE, /* SUBroutine SETs new state on exit */ + ST_ILL, /* Illegal */ + + N_STATES /* number of states */ +}; + +enum Q931_events { + + EV_SETUPRQ, /* setup request from L4 */ + EV_DISCRQ, /* disconnect request from L4 */ + EV_RELRQ, /* release request from L4 */ + EV_ALERTRQ, /* alerting request from L4 */ + EV_SETACRS, /* setup response accept from l4 */ + EV_SETRJRS, /* setup response reject from l4 */ + EV_SETDCRS, /* setup response dontcare from l4 */ + + EV_SETUP, /* incoming SETUP message from L2 */ + EV_STATUS, /* incoming STATUS message from L2 */ + EV_RELEASE, /* incoming RELEASE message from L2 */ + EV_RELCOMP, /* incoming RELEASE COMPLETE from L2 */ + EV_SETUPAK, /* incoming SETUP ACK message from L2 */ + EV_CALLPRC, /* incoming CALL PROCEEDING from L2 */ + EV_ALERT, /* incoming ALERT message from L2 */ + EV_CONNECT, /* incoming CONNECT message from L2 */ + EV_PROGIND, /* incoming Progress IND from L2 */ + EV_DISCONN, /* incoming DISCONNECT message from L2 */ + EV_CONACK, /* incoming CONNECT ACK message from L2 */ + EV_STATENQ, /* incoming STATUS ENQ message from L2 */ + EV_INFO, /* incoming INFO message from L2 */ + EV_FACILITY, /* FACILITY message */ + + EV_T303EXP, /* Timer T303 expired */ + EV_T305EXP, /* Timer T305 expired */ + EV_T308EXP, /* Timer T308 expired */ + EV_T309EXP, /* Timer T309 expired */ + EV_T310EXP, /* Timer T310 expired */ + EV_T313EXP, /* Timer T313 expired */ + + EV_DLESTIN, /* dl establish indication from l2 */ + EV_DLRELIN, /* dl release indication from l2 */ + EV_DLESTCF, /* dl establish confirm from l2 */ + EV_DLRELCF, /* dl release indication from l2 */ + + EV_ILL, /* Illegal */ + N_EVENTS +}; + +#endif /* _I4B_L3FSM_H_ */ diff --git a/sys/i4b/layer3/i4b_l3timer.c b/sys/i4b/layer3/i4b_l3timer.c new file mode 100644 index 0000000..6c1a2d3 --- /dev/null +++ b/sys/i4b/layer3/i4b_l3timer.c @@ -0,0 +1,347 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l3timer.c - timer and timeout handling for layer 3 + * ------------------------------------------------------ + * + * $Id: i4b_l3timer.c,v 1.9 1998/12/05 18:05:35 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:33:00 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> + +#include <i4b/layer4/i4b_l4.h> + +/*---------------------------------------------------------------------------* + * stop all layer 3 timers + *---------------------------------------------------------------------------*/ +void i4b_l3_stop_all_timers(call_desc_t *cd) +{ + T303_stop(cd); + T305_stop(cd); + T308_stop(cd); + T309_stop(cd); + T310_stop(cd); + T313_stop(cd); +} + +/*---------------------------------------------------------------------------* + * timer T303 timeout function + *---------------------------------------------------------------------------*/ +static void +T303_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T303_timeout", ("SETUP not answered, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T303EXP); +} + +/*---------------------------------------------------------------------------* + * timer T303 start + *---------------------------------------------------------------------------*/ +void +T303_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T303_start", ("cr = %d\n", cd->cr)); + cd->T303 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T303_callout = timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL); +#else + timeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, T303VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T303 stop + *---------------------------------------------------------------------------*/ +void +T303_stop(call_desc_t *cd) +{ + if(cd->T303 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd, cd->T303_callout); +#else + untimeout((TIMEOUT_FUNC_T)T303_timeout, (void *)cd); +#endif + cd->T303 = TIMER_IDLE; + } + DBGL3(L3_T_MSG, "T303_stop", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T305 timeout function + *---------------------------------------------------------------------------*/ +static void +T305_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T305_timeout", ("DISC not answered, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T305EXP); +} + +/*---------------------------------------------------------------------------* + * timer T305 start + *---------------------------------------------------------------------------*/ +void +T305_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T305_start", ("cr = %d\n", cd->cr)); + cd->T305 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T305_callout = timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL); +#else + timeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, T305VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T305 stop + *---------------------------------------------------------------------------*/ +void +T305_stop(call_desc_t *cd) +{ + if(cd->T305 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd, cd->T305_callout); +#else + untimeout((TIMEOUT_FUNC_T)T305_timeout, (void *)cd); +#endif + cd->T305 = TIMER_IDLE; + } + DBGL3(L3_T_MSG, "T305_stop", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T308 timeout function + *---------------------------------------------------------------------------*/ +static void +T308_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T308_timeout", ("REL not answered, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T308EXP); +} + +/*---------------------------------------------------------------------------* + * timer T308 start + *---------------------------------------------------------------------------*/ +void +T308_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T308_start", ("cr = %d\n", cd->cr)); + cd->T308 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T308_callout = timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL); +#else + timeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, T308VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T308 stop + *---------------------------------------------------------------------------*/ +void +T308_stop(call_desc_t *cd) +{ + if(cd->T308 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd, cd->T308_callout); +#else + untimeout((TIMEOUT_FUNC_T)T308_timeout, (void *)cd); +#endif + cd->T308 = TIMER_IDLE; + } + DBGL3(L3_T_MSG, "T308_stop", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T309 timeout function + *---------------------------------------------------------------------------*/ +static void +T309_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T309_timeout", ("datalink not reconnected, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T309EXP); +} + +/*---------------------------------------------------------------------------* + * timer T309 start + *---------------------------------------------------------------------------*/ +void +T309_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T309_start", ("cr = %d\n", cd->cr)); + cd->T309 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T309_callout = timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL); +#else + timeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, T309VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T309 stop + *---------------------------------------------------------------------------*/ +void +T309_stop(call_desc_t *cd) +{ + if(cd->T309 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd, cd->T309_callout); +#else + untimeout((TIMEOUT_FUNC_T)T309_timeout, (void *)cd); +#endif + cd->T309 = TIMER_IDLE; + } + DBGL3(L3_T_MSG, "T309_stop", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T310 timeout function + *---------------------------------------------------------------------------*/ +static void +T310_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T310_timeout", ("CALL PROC timeout, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T310EXP); +} + +/*---------------------------------------------------------------------------* + * timer T310 start + *---------------------------------------------------------------------------*/ +void +T310_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T310_start", ("cr = %d\n", cd->cr)); + cd->T310 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T310_callout = timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL); +#else + timeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, T310VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T310 stop + *---------------------------------------------------------------------------*/ +void +T310_stop(call_desc_t *cd) +{ + if(cd->T310 != TIMER_IDLE) + { +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd, cd->T310_callout); +#else + untimeout((TIMEOUT_FUNC_T)T310_timeout, (void *)cd); +#endif + cd->T310 = TIMER_IDLE; + } + DBGL3(L3_T_MSG, "T310_stop", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T313 timeout function + *---------------------------------------------------------------------------*/ +static void +T313_timeout(call_desc_t *cd) +{ + DBGL3(L3_T_ERR, "T313_timeout", ("CONN ACK not received, cr = %d\n", cd->cr)); + next_l3state(cd, EV_T313EXP); +} + +/*---------------------------------------------------------------------------* + * timer T313 start + *---------------------------------------------------------------------------*/ +void +T313_start(call_desc_t *cd) +{ + DBGL3(L3_T_MSG, "T313_start", ("cr = %d\n", cd->cr)); + cd->T313 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T313_callout = timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL); +#else + timeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, T313VAL); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T313 stop + *---------------------------------------------------------------------------*/ +void +T313_stop(call_desc_t *cd) +{ + if(cd->T313 != TIMER_IDLE) + { + cd->T313 = TIMER_IDLE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd, cd->T313_callout); +#else + untimeout((TIMEOUT_FUNC_T)T313_timeout, (void *)cd); +#endif + } + DBGL3(L3_T_MSG, "T313_stop", ("cr = %d\n", cd->cr)); +} + +#endif /* NI4BQ931 > 0 */ + diff --git a/sys/i4b/layer3/i4b_l4if.c b/sys/i4b/layer3/i4b_l4if.c new file mode 100644 index 0000000..55d9bb9 --- /dev/null +++ b/sys/i4b/layer3/i4b_l4if.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4if.c - Layer 3 interface to Layer 4 + * ------------------------------------------- + * + * $Id: i4b_l4if.c,v 1.17 1998/12/05 18:05:36 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:33:16 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> + +#include <i4b/layer4/i4b_l4.h> + +extern void isic_settrace(int unit, int val); /*XXX*/ +extern int isic_gettrace(int unit); /*XXX*/ + +static void n_connect_request(u_int cdid); +static void n_connect_response(u_int cdid, int response, int cause); +static void n_disconnect_request(u_int cdid, int cause); +static void n_alert_request(u_int cdid); +static void n_mgmt_command(int unit, int cmd, int parm); + +/*---------------------------------------------------------------------------* + * i4b_mdl_status_ind - status indication from lower layers + *---------------------------------------------------------------------------*/ +int +i4b_mdl_status_ind(int unit, int status, int parm) +{ + int sendup; + int i; + + DBGL3(L3_MSG, "i4b_mdl_status_ind", ("unit = %d, status = %d, parm = %d\n", unit, status, parm)); + + switch(status) + { + case STI_ATTACH: + DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_ATTACH: attaching unit %d to controller %d\n", unit, nctrl)); + + /* init function pointers */ + + ctrl_desc[nctrl].N_CONNECT_REQUEST = n_connect_request; + ctrl_desc[nctrl].N_CONNECT_RESPONSE = n_connect_response; + ctrl_desc[nctrl].N_DISCONNECT_REQUEST = n_disconnect_request; + ctrl_desc[nctrl].N_ALERT_REQUEST = n_alert_request; + ctrl_desc[nctrl].N_SET_TRACE = isic_settrace; + ctrl_desc[nctrl].N_GET_TRACE = isic_gettrace; + ctrl_desc[nctrl].N_DOWNLOAD = NULL; /* only used by active cards */ + ctrl_desc[nctrl].N_DIAGNOSTICS = NULL; /* only used by active cards */ + ctrl_desc[nctrl].N_MGMT_COMMAND = n_mgmt_command; + + /* init type and unit */ + + ctrl_desc[nctrl].unit = unit; + ctrl_desc[nctrl].ctrl_type = CTRL_PASSIVE; + ctrl_desc[nctrl].card_type = parm; + + /* state fields */ + + ctrl_desc[nctrl].dl_est = DL_DOWN; + ctrl_desc[nctrl].bch_state[CHAN_B1] = BCH_ST_FREE; + ctrl_desc[nctrl].bch_state[CHAN_B2] = BCH_ST_FREE; + ctrl_desc[nctrl].tei = -1; + + /* init unit to controller table */ + + utoc_tab[unit] = nctrl; + + /* increment no. of controllers */ + + nctrl++; + + break; + + case STI_L1STAT: + i4b_l4_l12stat(unit, 1, parm); + DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L1STAT: unit %d layer 1 = %s\n", unit, status ? "up" : "down")); + break; + + case STI_L2STAT: + i4b_l4_l12stat(unit, 2, parm); + DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_L2STAT: unit %d layer 2 = %s\n", unit, status ? "up" : "down")); + break; + + case STI_TEIASG: + ctrl_desc[unit].tei = parm; + i4b_l4_teiasg(unit, parm); + DBGL3(L3_MSG, "i4b_mdl_status_ind", ("STI_TEIASG: unit %d TEI = %d = 0x%02x\n", unit, parm, parm)); + break; + + case STI_PDEACT: /* L1 T4 timeout */ + DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_PDEACT: unit %d TEI = %d = 0x%02x\n", unit, parm, parm)); + + sendup = 0; + + for(i=0; i < N_CALL_DESC; i++) + { + if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + if(call_desc[i].cdid != CDID_UNUSED) + sendup++; + } + } + + ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].tei = -1; + + if(sendup) + i4b_l4_pdeact(unit, sendup); + break; + + case STI_NOL1ACC: /* no outgoing access to S0 */ + DBGL3(L3_ERR, "i4b_mdl_status_ind", ("STI_NOL1ACC: unit %d no outgoing access to S0\n", unit)); + + for(i=0; i < N_CALL_DESC; i++) + { + if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + if(call_desc[i].cdid != CDID_UNUSED) + { + SET_CAUSE_TYPE(call_desc[i].cause_in, CAUSET_I4B); + SET_CAUSE_VAL(call_desc[i].cause_in, CAUSE_I4B_L1ERROR); + i4b_l4_disconnect_ind(&(call_desc[i])); + } + } + } + + ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].tei = -1; + break; + + default: + DBGL3(L3_ERR, "i4b_mdl_status_ind", ("ERROR, unit %d, unknown status value %d!\n", unit, status)); + break; + } + return(0); +} + +/*---------------------------------------------------------------------------* + * send command to the lower layers + *---------------------------------------------------------------------------*/ +static void +n_mgmt_command(int unit, int cmd, int parm) +{ + int i; + + switch(cmd) + { + case CMR_DOPEN: + DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DOPEN for unit %d\n", unit)); + + for(i=0; i < N_CALL_DESC; i++) + { + if( (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit)) + { + call_desc[i].cdid = CDID_UNUSED; + } + } + + ctrl_desc[utoc_tab[unit]].dl_est = DL_DOWN; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B1] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].bch_state[CHAN_B2] = BCH_ST_FREE; + ctrl_desc[utoc_tab[unit]].tei = -1; + break; + + case CMR_DCLOSE: + DBGL3(L3_MSG, "n_mgmt_command", ("CMR_DCLOSE for unit %d\n", unit)); + break; + + default: + break; + + } + + MDL_Command_Req(unit, cmd, parm); + +} + +/*---------------------------------------------------------------------------* + * handle connect request message from userland + *---------------------------------------------------------------------------*/ +static void +n_connect_request(u_int cdid) +{ + call_desc_t *cd; + + cd = cd_by_cdid(cdid); + + next_l3state(cd, EV_SETUPRQ); +} + +/*---------------------------------------------------------------------------* + * handle setup response message from userland + *---------------------------------------------------------------------------*/ +static void +n_connect_response(u_int cdid, int response, int cause) +{ + call_desc_t *cd; + int chstate; + + cd = cd_by_cdid(cdid); + + T400_stop(cd); + + cd->response = response; + cd->cause_out = cause; + + switch(response) + { + case SETUP_RESP_ACCEPT: + next_l3state(cd, EV_SETACRS); + chstate = BCH_ST_USED; + break; + + case SETUP_RESP_REJECT: + next_l3state(cd, EV_SETRJRS); + chstate = BCH_ST_FREE; + break; + + case SETUP_RESP_DNTCRE: + next_l3state(cd, EV_SETDCRS); + chstate = BCH_ST_FREE; + break; + + default: /* failsafe */ + next_l3state(cd, EV_SETDCRS); + chstate = BCH_ST_FREE; + DBGL3(L3_ERR, "n_connect_response", ("unknown response, doing SETUP_RESP_DNTCRE")); + break; + } + + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + ctrl_desc[cd->controller].bch_state[cd->channelid] = chstate; + } + else + { + DBGL3(L3_ERR, "n_connect_response", ("ERROR, invalid channel %d\n", cd->channelid)); + } +} + +/*---------------------------------------------------------------------------* + * handle disconnect request message from userland + *---------------------------------------------------------------------------*/ +static void +n_disconnect_request(u_int cdid, int cause) +{ + call_desc_t *cd; + + cd = cd_by_cdid(cdid); + + cd->cause_out = cause; + + next_l3state(cd, EV_DISCRQ); +} + +/*---------------------------------------------------------------------------* + * handle alert request message from userland + *---------------------------------------------------------------------------*/ +static void +n_alert_request(u_int cdid) +{ + call_desc_t *cd; + + cd = cd_by_cdid(cdid); + + next_l3state(cd, EV_ALERTRQ); +} + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer3/i4b_q931.c b/sys/i4b/layer3/i4b_q931.c new file mode 100644 index 0000000..6c111d1 --- /dev/null +++ b/sys/i4b/layer3/i4b_q931.c @@ -0,0 +1,624 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_q931.c - Q931 received messages handling + * -------------------------------------------- + * + * $Id: i4b_q931.c,v 1.18 1998/12/05 18:05:38 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:33:36 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif + +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> + +#include <i4b/layer4/i4b_l4.h> + +#ifndef __FreeBSD__ +#define memcpy(d,s,l) bcopy(s,d,l) +#endif + +unsigned int i4b_l3_debug = L3_DEBUG_DEFAULT; + +call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */ +ctrl_desc_t ctrl_desc[MAX_CONTROLLERS]; /* controller description array */ +int utoc_tab[MAX_CONTROLLERS]; /* unit to controller conversion */ + +/* protocol independent causes -> Q.931 causes */ + +unsigned char cause_tab_q931[CAUSE_I4B_MAX] = { + CAUSE_Q850_NCCLR, /* CAUSE_I4B_NORMAL -> normal call clearing */ + CAUSE_Q850_USRBSY, /* CAUSE_I4B_BUSY -> user busy */ + CAUSE_Q850_NOCAVAIL, /* CAUSE_I4B_NOCHAN -> no circuit/channel available*/ + CAUSE_Q850_INCDEST, /* CAUSE_I4B_INCOMP -> incompatible destination */ + CAUSE_Q850_CALLREJ, /* CAUSE_I4B_REJECT -> call rejected */ + CAUSE_Q850_DSTOOORDR, /* CAUSE_I4B_OOO -> destination out of order */ + CAUSE_Q850_TMPFAIL, /* CAUSE_I4B_TMPFAIL -> temporary failure */ +}; + +/*---------------------------------------------------------------------------* + * setup cr ref flag according to direction + *---------------------------------------------------------------------------*/ +unsigned char +setup_cr(call_desc_t *cd, unsigned char cr) +{ + if(cd->crflag == CRF_ORIG) + return(cr & 0x7f); /* clear cr ref flag */ + else if(cd->crflag == CRF_DEST) + return(cr | 0x80); /* set cr ref flag */ + else + panic("setup_cr: invalid crflag!\n"); +} + +/*---------------------------------------------------------------------------* + * decode and process a Q.931 message + *---------------------------------------------------------------------------*/ +void +i4b_decode_q931(int unit, int msg_len, u_char *msg_ptr) +{ + call_desc_t *cd; + int codeset = CODESET_0; + int old_codeset = CODESET_0; + int shift_flag = UNSHIFTED; + int crlen = 0; + int crval = 0; + int crflag = 0; + int i; + int offset; + int s; + + /* check protocol discriminator */ + + if(*msg_ptr != PD_Q931) + { + DBGL3(L3_P_ERR, "i4b_decode_q931", ("protocol discriminator 0x%x != Q.931\n", *msg_ptr)); + return; + } + msg_ptr++; + msg_len--; + + s = SPLI4B(); /* this has to be protected ! */ + + /* extract call reference */ + + crlen = *msg_ptr & CRLENGTH_MASK; + msg_ptr++; + msg_len--; + + if(crlen != 0) + { + crval += *msg_ptr & 0x7f; + crflag = (*msg_ptr >> 7) & 0x01; + msg_ptr++; + msg_len--; + + for(i=1; i < crlen; i++) + { + crval += *msg_ptr; + msg_ptr++; + msg_len--; + } + } + else + { + crval = 0; + crflag = 0; + } + + DBGL3(L3_P_MSG, "i4b_decode_q931", ("Call Ref, len %d, val %d, flag %d\n", crlen, crval, crflag)); + + /* find or allocate calldescriptor */ + + if((cd = cd_by_unitcr(unit, crval, + crflag == CRF_DEST ? CRF_ORIG : CRF_DEST)) == NULL) + { + if(*msg_ptr == SETUP) + { + /* get and init new calldescriptor */ + + cd = reserve_cd(); /* cdid filled in */ + cd->controller = utoc_tab[unit]; + cd->cr = crval; + cd->crflag = CRF_DEST; /* we are the dest side */ + cd->ilt = NULL; /* reset link tab ptrs */ + cd->dlt = NULL; + } + else + { +/*XXX*/ if(crval != 0) /* ignore global call references */ + { + DBGL3(L3_P_ERR, "i4b_decode_q931", ("cannot find calldescriptor for cr = 0x%x, crflag = 0x%x, msg = 0x%x, frame = ", crval, crflag, *msg_ptr)); + i4b_print_frame(msg_len, msg_ptr); + } + splx(s); + return; + } + } + + splx(s); + + /* decode and handle message type */ + + i4b_decode_q931_message(unit, cd, *msg_ptr); + msg_ptr++; + msg_len--; + + /* process information elements */ + + while(msg_len > 0) + { + /* check for shift codeset IE */ + + if((*msg_ptr & 0x80) && ((*msg_ptr & 0xf0) == SOIE_SHIFT)) + { + if(!(*msg_ptr & SHIFT_LOCK)) + shift_flag = SHIFTED; + + old_codeset = codeset; + codeset = *msg_ptr & CODESET_MASK; + + if((shift_flag != SHIFTED) && + (codeset <= old_codeset)) + { + DBGL3(L3_P_ERR, "i4b_decode_q931", ("Q.931 lockingshift proc violation, shift %d -> %d\n", old_codeset, codeset)); + codeset = old_codeset; + } + msg_len--; + msg_ptr++; + } + + /* process one IE for selected codeset */ + + switch(codeset) + { + case CODESET_0: + offset = i4b_decode_q931_cs0_ie(unit, cd, msg_len, msg_ptr); + msg_len -= offset; + msg_ptr += offset; + break; + + default: + DBGL3(L3_P_ERR, "i4b_decode_q931", ("unknown codeset %d, ", codeset)); + i4b_print_frame(msg_len, msg_ptr); + msg_len = 0; + break; + } + + /* check for non-locking shifts */ + + if(shift_flag == SHIFTED) + { + shift_flag = UNSHIFTED; + codeset = old_codeset; + } + } + next_l3state(cd, cd->event); +} + +/*---------------------------------------------------------------------------* + * decode and process one Q.931 codeset 0 information element + *---------------------------------------------------------------------------*/ +int +i4b_decode_q931_cs0_ie(int unit, call_desc_t *cd, int msg_len, u_char *msg_ptr) +{ + int i, j; + char *p; + + switch(*msg_ptr) + { + /* single byte IE's */ + + case IEI_SENDCOMPL: + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_SENDCOMPL\n")); + return(1); + break; + + /* multi byte IE's */ + + case IEI_BEARERCAP: /* bearer capability */ + switch(msg_ptr[2]) + { + case 0x80: /* speech */ + case 0x89: /* restricted digital info */ + case 0x90: /* 3.1KHz audio */ +/* XXX */ cd->bprot = BPROT_NONE; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Telephony\n")); + break; + + case 0x88: /* unrestricted digital info */ +/* XXX */ cd->bprot = BPROT_RHDLC; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - Raw HDLC\n")); + break; + + default: +/* XXX */ cd->bprot = BPROT_NONE; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_BEARERCAP - No Protocol\n")); + break; + } + break; + + case IEI_CAUSE: /* cause */ + if(msg_ptr[2] & 0x80) + { + cd->cause_in = msg_ptr[3] & 0x7f; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[3] & 0x7f)); + } + else + { + cd->cause_in = msg_ptr[4] & 0x7f; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CAUSE = %d\n", msg_ptr[4] & 0x7f)); + } + break; + + case IEI_CHANNELID: /* channel id */ + if((msg_ptr[2] & 0xf4) != 0x80) + { + cd->channelid = CHAN_NO; + DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IEI_CHANNELID, unsupported value 0x%x\n", msg_ptr[2])); + } + else + { + switch(msg_ptr[2] & 0x03) + { + case IE_CHAN_ID_NO: + cd->channelid = CHAN_NO; + break; + case IE_CHAN_ID_B1: + cd->channelid = CHAN_B1; + break; + case IE_CHAN_ID_B2: + cd->channelid = CHAN_B2; + break; + case IE_CHAN_ID_ANY: + cd->channelid = CHAN_ANY; + break; + } + cd->channelexcl = (msg_ptr[2] & 0x08) >> 3; + + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CHANNELID - channel %d, exclusive = %d\n", cd->channelid, cd->channelexcl)); + + /* if this is a setup message, reserve channel */ + + if(cd->event == EV_SETUP) + { + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + if(ctrl_desc[cd->controller].bch_state[cd->channelid] == BCH_ST_FREE) + ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; + else + DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("IE ChannelID, Channel NOT free!!\n")); + } + else if(cd->channelid == CHAN_NO) + { + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IE ChannelID, SETUP with channel = No channel (CW)\n")); + } + else /* cd->channelid == CHAN_ANY */ + { + DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("ERROR: IE ChannelID, SETUP with channel = Any channel!\n")); + } + } + } + break; + + case IEI_CALLINGPN: /* calling party no */ + if(msg_ptr[2] & 0x80) /* no presentation/screening indicator ? */ + { + memcpy(cd->src_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1)); + cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 1)] = '\0'; + cd->scr_ind = SCR_NONE; + } + else + { + memcpy(cd->src_telno, &msg_ptr[4], min(TELNO_MAX, msg_ptr[1]-2)); + cd->src_telno[min(TELNO_MAX, msg_ptr[1] - 2)] = '\0'; + cd->scr_ind = (msg_ptr[3] & 0x03) + SCR_USR_NOSC; + } + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLINGPN = %s\n", cd->src_telno)); + break; + + case IEI_CALLEDPN: /* called party number */ + memcpy(cd->dst_telno, &msg_ptr[3], min(TELNO_MAX, msg_ptr[1]-1)); + cd->dst_telno[min(TELNO_MAX, msg_ptr [1] - 1)] = '\0'; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLED = %s\n", cd->dst_telno)); + break; + + case IEI_CALLSTATE: /* call state */ + cd->call_state = msg_ptr[2] & 0x3f; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CALLSTATE = %d\n", cd->call_state)); + break; + + case IEI_PROGRESSI: /* progress indicator */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_PROGRESSINDICATOR\n")); + break; + + case IEI_DISPLAY: /* display */ + /* CHANGED BY <chris@medis.de> */ + memcpy(cd->display, &msg_ptr[2], min(DISPLAY_MAX, msg_ptr[1])); + cd->display[min(DISPLAY_MAX, msg_ptr[1])] = '\0'; + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DISPLAY = %s\n", cd->display)); + break; + + case IEI_DATETIME: /* date/time */ + i = 2; + j = msg_ptr[1]; + p = &(cd->datetime[0]); + *p = '\0'; + + for(j = msg_ptr[1]; j > 0; j--, i++) + sprintf(p+strlen(p), "%02d", msg_ptr[i]); + + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_DATETIME = %s\n", cd->datetime)); + break; + + case IEI_FACILITY: /* facility */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_FACILITY\n")); + if(i4b_aoc(msg_ptr, cd) > -1) + i4b_l4_charging_ind(cd); + break; + + case IEI_CONCTDNO: /* connected number */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_CONCTDNO\n")); + break; + + case IEI_NETSPCFAC: /* network specific fac */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_NETSPCFAC\n")); + break; + + case IEI_LLCOMPAT: /* low layer compat */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_LLCOMPAT\n")); + break; + + case IEI_HLCOMPAT: /* high layer compat */ + DBGL3(L3_P_MSG, "i4b_decode_q931_codeset0", ("IEI_HLCOMPAT\n")); + break; + + default: + DBGL3(L3_P_ERR, "i4b_decode_q931_codeset0", ("Unknown IE %d - ", *msg_ptr)); + i4b_print_frame(msg_ptr[1]+2, msg_ptr); + break; + } + return(msg_ptr[1] + 2); +} + +/*---------------------------------------------------------------------------* + * decode and process one Q.931 codeset 0 information element + *---------------------------------------------------------------------------*/ +void +i4b_decode_q931_message(int unit, call_desc_t *cd, u_char message_type) +{ + cd->event = EV_ILL; + + switch(message_type) + { + /* call establishment */ + + case ALERT: + cd->event = EV_ALERT; + DBGL3(L3_PRIM, "rx ALERT", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case CALL_PROCEEDING: + cd->event = EV_CALLPRC; + DBGL3(L3_PRIM, "rx CALL-PROC", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case PROGRESS: + cd->event = EV_PROGIND; + DBGL3(L3_PRIM, "rx PROGRESS", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case SETUP: + DBGL3(L3_PRIM, "rx SETUP", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->bprot = BPROT_NONE; + cd->cause_in = 0; + cd->cause_out = 0; + cd->dst_telno[0] = '\0'; + cd->src_telno[0] = '\0'; + cd->channelid = CHAN_NO; + cd->channelexcl = 0; + cd->display[0] = '\0'; + cd->datetime[0] = '\0'; + cd->event = EV_SETUP; + break; + + case CONNECT: + DBGL3(L3_PRIM, "rx CONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->datetime[0] = '\0'; + cd->event = EV_CONNECT; + break; + + case SETUP_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx SETUP-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_SETUPAK; + break; + + case CONNECT_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx CONNECT-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_CONACK; + break; + + /* call information */ + + case USER_INFORMATION: + DBGL3(L3_PRIM, "rx USER-INFO", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case SUSPEND_REJECT: + DBGL3(L3_PRIM, "rx SUSPEND-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RESUME_REJECT: + DBGL3(L3_PRIM, "rx RESUME-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case HOLD: + DBGL3(L3_PRIM, "rx HOLD", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case SUSPEND: + DBGL3(L3_PRIM, "rx SUSPEND", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RESUME: + DBGL3(L3_PRIM, "rx RESUME", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case HOLD_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx HOLD-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case SUSPEND_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx SUSPEND-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RESUME_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx RESUME-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case HOLD_REJECT: + DBGL3(L3_PRIM, "rx HOLD-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RETRIEVE: + DBGL3(L3_PRIM, "rx RETRIEVE", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RETRIEVE_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx RETRIEVE-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RETRIEVE_REJECT: + DBGL3(L3_PRIM, "rx RETRIEVE-REJ", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + /* call clearing */ + + case DISCONNECT: + DBGL3(L3_PRIM, "rx DISCONNECT", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_DISCONN; + break; + + case RESTART: + DBGL3(L3_PRIM, "rx RESTART", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RELEASE: + DBGL3(L3_PRIM, "rx RELEASE", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_RELEASE; + break; + + case RESTART_ACKNOWLEDGE: + DBGL3(L3_PRIM, "rx RESTART-ACK", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case RELEASE_COMPLETE: + DBGL3(L3_PRIM, "rx RELEASE-COMPLETE", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_RELCOMP; + break; + + /* misc messages */ + + case SEGMENT: + DBGL3(L3_PRIM, "rx SEGMENT", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case FACILITY: + DBGL3(L3_PRIM, "rx FACILITY", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_FACILITY; + break; + + case REGISTER: + DBGL3(L3_PRIM, "rx REGISTER", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case NOTIFY: + DBGL3(L3_PRIM, "rx NOTIFY", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case STATUS_ENQUIRY: + DBGL3(L3_PRIM, "rx STATUS-ENQ", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_STATENQ; + break; + + case CONGESTION_CONTROL: + DBGL3(L3_PRIM, "rx CONGESTION-CONTROL", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + break; + + case INFORMATION: + DBGL3(L3_PRIM, "rx INFORMATION", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_INFO; + break; + + case STATUS: + DBGL3(L3_PRIM, "rx STATUS", ("unit %d, cr = 0x%02x\n", unit, cd->cr)); + cd->event = EV_STATUS; + break; + + default: + DBGL3(L3_P_ERR, "rx UNKNOWN msg", ("unit %d, cr = 0x%02x, msg = 0x%02x\n", unit, cd->cr, message_type)); + break; + } +} + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer3/i4b_q931.h b/sys/i4b/layer3/i4b_q931.h new file mode 100644 index 0000000..cb916b0 --- /dev/null +++ b/sys/i4b/layer3/i4b_q931.h @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_q931.h - Q931 handling header file + * -------------------------------------- + * + * $Id: i4b_q931.h,v 1.5 1998/12/05 18:05:39 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:33:53 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_Q931_H_ +#define _I4B_Q931_H_ + +/* extension bit */ + +#define EXT_LAST 0x80 /* last octett */ + +/* reserve space in mbuf */ + +#define I_FRAME_HDRLEN 4 /* to be added by layer 2 */ + +/* SHIFT */ + +#define CODESET_MASK 0x07 +#define UNSHIFTED 0 +#define SHIFTED 1 +#define CRLENGTH_MASK 0x0f + +/* CONNECT */ + +#define MSG_CONNECT_LEN 4 /* length of a connect message */ + +/* DISCONNECT */ + +#define MSG_DISCONNECT_LEN 8 /* length of a disconnect message */ + +/* RELEASE COMPLETE */ + +#define MSG_RELEASE_COMPLETE_LEN 8 /* length of release complete msg */ + +/* for outgoing causes */ + +#define CAUSE_LEN 2 +#define CAUSE_STD_LOC_OUT 0x80 /* std = CCITT, loc = user */ + +/* SETUP */ + +#define MSG_SETUP_LEN 18 /* without number strings ! */ + +#define IEI_BEARERCAP_LEN 2 /* 2 octetts lenght */ + +#define IT_CAP_SPEECH 0x80 /* BC: information xfer capability */ +#define IT_CAP_UNR_DIG_INFO 0x88 /* BC: information xfer capability */ + +#define IT_RATE_64K 0x90 /* BC: information xfer rate */ +#define IT_UL1_G711A 0xa3 /* layer1 proto G.711 A-law */ + +#define IEI_CHANNELID_LEN 0x01 /* length of channel id */ +#define CHANNELID_B1 0x81 /* channel = B1 (outgoing) */ +#define CHANNELID_B2 0x82 /* channel = B2 (outgoing) */ +#define CHANNELID_ANY 0x83 /* channel = any channel (outgoing) */ + +#define IE_CHAN_ID_NO 0x00 /* no channel (incoming) */ +#define IE_CHAN_ID_B1 0x01 /* B1 channel (incoming) */ +#define IE_CHAN_ID_B2 0x02 /* B2 channel (incoming) */ +#define IE_CHAN_ID_ANY 0x03 /* ANY channel (incoming) */ + +#define NUMBER_TYPEPLAN 0x81 /* type of number/numbering plan */ + +#define IEI_CALLINGPN_LEN 1 /* without number string ! */ + +#define IEI_CALLEDPN_LEN 1 /* without number string ! */ + +/* CONNECT_ACK */ + +#define MSG_CONNECT_ACK_LEN 4 /* length of a connect ack message */ + +/* STATUS */ + +#define MSG_STATUS_LEN 11 +#define CALLSTATE_LEN 1 + +/* RELEASE */ + +#define MSG_RELEASE_LEN 8 /* length of release msg */ + +/* ALERT */ + +#define MSG_ALERT_LEN 4 /* length of a alert message */ + +#endif /* _I4B_Q931_H_ */ diff --git a/sys/i4b/layer3/i4b_q932fac.c b/sys/i4b/layer3/i4b_q932fac.c new file mode 100644 index 0000000..487ce00 --- /dev/null +++ b/sys/i4b/layer3/i4b_q932fac.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_q932fac.c - Q932 facility handling + * -------------------------------------- + * + * $Id: i4b_q932fac.c,v 1.5 1998/12/05 18:05:41 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:34:11 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef __FreeBSD__ +#include "i4bq931.h" +#else +#define NI4BQ931 1 +#endif +#if NI4BQ931 > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer3/i4b_l3fsm.h> +#include <i4b/layer3/i4b_q931.h> +#include <i4b/layer3/i4b_q932fac.h> + +#include <i4b/layer4/i4b_l4.h> + +static int do_component(int length); +static void next_state(int class, int form, int code, int val); + +static int byte_len; +static unsigned char *byte_buf; +static int state; + +static int units; +static int operation_value; + +/*---------------------------------------------------------------------------* + * decode Q.931/Q.932 facility info element + *---------------------------------------------------------------------------*/ +int +i4b_aoc(unsigned char *buf, call_desc_t *cd) +{ + int len; + + cd->units_type = CHARGE_INVALID; + cd->units = -1; + + buf++; /* length */ + + len = *buf; + + buf++; /* protocol profile */ + + switch(*buf & 0x1f) + { + case FAC_PROTO_ROP: + break; + + case FAC_PROTO_CMIP: + DBGL3(L3_A_MSG, "i4b_facility", ("CMIP Protocol (Q.941), UNSUPPORTED\n")); + return(-1); + break; + + case FAC_PROTO_ACSE: + DBGL3(L3_A_MSG, "i4b_facility", ("ACSE Protocol (X.217/X.227), UNSUPPORTED!\n")); + return(-1); + break; + + default: + DBGL3(L3_A_ERR, "i4b_facility", ("Unknown Protocol, UNSUPPORTED!\n")); + return(-1); + break; + } + + DBGL3(L3_A_MSG, "i4b_facility", ("Remote Operations Protocol\n")); + + /* next byte */ + + buf++; + len--; + + /* initialize variables for do_component */ + + byte_len = 0; + byte_buf = buf; + state = ST_EXP_COMP_TYP; + + /* decode facility */ + + do_component(len); + + switch(operation_value) + { + case FAC_OPVAL_AOC_D_CUR: + cd->units_type = CHARGE_AOCD; + cd->units = 0; + return(0); + break; + + case FAC_OPVAL_AOC_D_UNIT: + cd->units_type = CHARGE_AOCD; + cd->units = units; + return(0); + break; + + case FAC_OPVAL_AOC_E_CUR: + cd->units_type = CHARGE_AOCE; + cd->units = 0; + return(0); + break; + + case FAC_OPVAL_AOC_E_UNIT: + cd->units_type = CHARGE_AOCE; + cd->units = units; + return(0); + break; + + default: + cd->units_type = CHARGE_INVALID; + cd->units = -1; + return(-1); + break; + } + return(-1); +} + +/*---------------------------------------------------------------------------* + * handle a component recursively + *---------------------------------------------------------------------------*/ +static int +do_component(int length) +{ + int comp_tag_class; /* component tag class */ + int comp_tag_form; /* component form: constructor or primitive */ + int comp_tag_code; /* component code depending on class */ + int comp_length = 0; /* component length */ + +again: + + /*----------------------------------------*/ + /* first component element: component tag */ + /*----------------------------------------*/ + + /* tag class bits */ + + comp_tag_class = (*byte_buf & 0xc0) >> 6; + + switch(comp_tag_class) + { + case FAC_TAGCLASS_UNI: + break; + case FAC_TAGCLASS_APW: + break; + case FAC_TAGCLASS_COS: + break; + case FAC_TAGCLASS_PRU: + break; + } + + /* tag form bit */ + + comp_tag_form = (*byte_buf & 0x20) > 5; + + /* tag code bits */ + + comp_tag_code = *byte_buf & 0x1f; + + if(comp_tag_code == 0x1f) + { + comp_tag_code = 0; + + byte_buf++; + byte_len++; + + while(*byte_buf & 0x80) + { + comp_tag_code += (*byte_buf & 0x7f); + byte_buf++; + byte_len++; + } + comp_tag_code += (*byte_buf & 0x7f); + } + else + { + comp_tag_code = (*byte_buf & 0x1f); + } + + byte_buf++; + byte_len++; + + /*--------------------------------------------*/ + /* second component element: component length */ + /*--------------------------------------------*/ + + comp_length = 0; + + if(*byte_buf & 0x80) + { + int i = *byte_buf & 0x7f; + + byte_len += i; + + for(;i > 0;i++) + { + byte_buf++; + comp_length += (*byte_buf * (i*256)); + } + } + else + { + comp_length = *byte_buf & 0x7f; + } + + next_state(comp_tag_class, comp_tag_form, comp_tag_code, -1); + + byte_len++; + byte_buf++; + + /*---------------------------------------------*/ + /* third component element: component contents */ + /*---------------------------------------------*/ + + if(comp_tag_form) /* == constructor */ + { + do_component(comp_length); + } + else + { + int val = 0; + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + switch(comp_tag_code) + { + case FAC_CODEUNI_INT: + case FAC_CODEUNI_ENUM: + case FAC_CODEUNI_BOOL: + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + } + } + break; + default: + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + byte_buf++; + byte_len++; + } + } + break; + } + } + + else /* comp_tag_class != FAC_TAGCLASS_UNI */ + { + if(comp_length) + { + int i; + + for(i = comp_length-1; i >= 0; i--) + { + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + } + } + } + next_state(comp_tag_class, comp_tag_form, comp_tag_code, val); + } + + if(byte_len < length) + goto again; + + return(byte_len); +} + +/*---------------------------------------------------------------------------* + * invoke component + *---------------------------------------------------------------------------*/ +static void +F_1_1(int val) +{ + if(val == -1) + { + state = ST_EXP_INV_ID; + } +} + +/*---------------------------------------------------------------------------* + * return result + *---------------------------------------------------------------------------*/ +static void +F_1_2(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} +/*---------------------------------------------------------------------------* + * return error + *---------------------------------------------------------------------------*/ +static void +F_1_3(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} +/*---------------------------------------------------------------------------* + * reject + *---------------------------------------------------------------------------*/ +static void +F_1_4(int val) +{ + if(val == -1) + state = ST_EXP_NIX; +} + +/*---------------------------------------------------------------------------* + * invoke id + *---------------------------------------------------------------------------*/ +static void +F_2(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Invoke ID = %d\n", val)); + state = ST_EXP_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * operation value + *---------------------------------------------------------------------------*/ +static void +F_3(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Operation Value = %d\n", val)); + + operation_value = val; + + if((val == FAC_OPVAL_AOC_D_UNIT) || (val == FAC_OPVAL_AOC_E_UNIT)) + { + units = 0; + state = ST_EXP_INFO; + } + else + { + state = ST_EXP_NIX; + } + } +} + +/*---------------------------------------------------------------------------* + * specific charging units + *---------------------------------------------------------------------------*/ +static void +F_4(int val) +{ + if(val == -1) + state = ST_EXP_RUL; +} + +/*---------------------------------------------------------------------------* + * free of charge + *---------------------------------------------------------------------------*/ +static void +F_4_1(int val) +{ + if(val == -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Free of Charge\n")); + /* units = 0; XXXX */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * charge not available + *---------------------------------------------------------------------------*/ +static void +F_4_2(int val) +{ + if(val == -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Charge not available\n")); + /* units = -1; XXXXXX ??? */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * recorded units list + *---------------------------------------------------------------------------*/ +static void +F_5(int val) +{ + if(val == -1) + state = ST_EXP_RU; +} + +/*---------------------------------------------------------------------------* + * recorded units + *---------------------------------------------------------------------------*/ +static void +F_6(int val) +{ + if(val == -1) + state = ST_EXP_RNOU; +} + +/*---------------------------------------------------------------------------* + * number of units + *---------------------------------------------------------------------------*/ +static void +F_7(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Number of Units = %d\n", val)); + units = val; + state = ST_EXP_TOCI; + } +} + +/*---------------------------------------------------------------------------* + * subtotal/total + *---------------------------------------------------------------------------*/ +static void +F_8(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Subtotal/Total = %d\n", val)); + /* type_of_charge = val; */ + state = ST_EXP_DBID; + } +} + +/*---------------------------------------------------------------------------* + * billing_id + *---------------------------------------------------------------------------*/ +static void +F_9(int val) +{ + if(val != -1) + { + DBGL3(L3_A_MSG, "i4b_facility", ("Billing ID = %d\n", val)); + /* billing_id = val; */ + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static struct statetab { + int currstate; /* input: current state we are in */ + int form; /* input: current tag form */ + int class; /* input: current tag class */ + int code; /* input: current tag code */ + void (*func)(int); /* output: func to exec */ +} statetab[] = { + +/* current state tag form tag class tag code function */ +/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/ + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 }, + {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 }, + {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 }, + {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 }, + {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 }, + {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 }, + {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 }, + {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 }, + {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 }, + {-1, -1, -1, -1, NULL } +}; + +/*---------------------------------------------------------------------------* + * state decode for do_component + *---------------------------------------------------------------------------*/ +static void +next_state(int class, int form, int code, int val) +{ + int i; + + for(i=0; ; i++) + { + if((statetab[i].currstate > state) || + (statetab[i].currstate == -1)) + { + break; + } + + if((statetab[i].currstate == state) && + (statetab[i].form == form) && + (statetab[i].class == class) && + (statetab[i].code == code)) + { + (*statetab[i].func)(val); + break; + } + } +} + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer3/i4b_q932fac.h b/sys/i4b/layer3/i4b_q932fac.h new file mode 100644 index 0000000..d7544a8 --- /dev/null +++ b/sys/i4b/layer3/i4b_q932fac.h @@ -0,0 +1,167 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_q932fac.h - Q932 facility handling header file + * -------------------------------------------------- + * + * $Id: i4b_q932fac.h,v 1.5 1998/12/18 17:17:57 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:17:23 1998] + * + *--------------------------------------------------------------------------- + * + * - Q.932 (03/93) Generic Procedures for the Control of + * ISDN Supplementaty Services + * - Q.950 (03/93) Supplementary Services Protocols, Structure and + * General Principles + * - ETS 300 179 (10/92) Advice Of Charge: charging information during + * the call (AOC-D) supplementary service Service description + * - ETS 300 180 (10/92) Advice Of Charge: charging information at the + * end of call (AOC-E) supplementary service Service description + * - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service + * Functional capabilities and information flows + * - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service + * Digital Subscriber Signalling System No. one (DSS1) protocol + * - X.208 Specification of Abstract Syntax Notation One (ASN.1) + * - X.209 Specification of Basic Encoding Rules for + * Abstract Syntax Notation One (ASN.1) + * - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag + * 1992, 3rd Edition (ISBN 3-89238-062-7) (german !) + * + *---------------------------------------------------------------------------*/ + +/* protocols */ +#define FAC_PROTO_ROP 0x11 +#define FAC_PROTO_CMIP 0x12 +#define FAC_PROTO_ACSE 0x13 + +/* tag classes */ +#define FAC_TAGCLASS_UNI 0x00 +#define FAC_TAGCLASS_APW 0x01 +#define FAC_TAGCLASS_COS 0x02 +#define FAC_TAGCLASS_PRU 0x03 + +/* tag forms */ +#define FAC_TAGFORM_PRI 0x00 +#define FAC_TAGFORM_CON 0x01 + +/* class UNIVERSAL values */ +#define FAC_CODEUNI_BOOL 1 +#define FAC_CODEUNI_INT 2 +#define FAC_CODEUNI_BITS 3 +#define FAC_CODEUNI_OCTS 4 +#define FAC_CODEUNI_NULL 5 +#define FAC_CODEUNI_OBJI 6 +#define FAC_CODEUNI_OBJD 7 +#define FAC_CODEUNI_EXT 8 +#define FAC_CODEUNI_REAL 9 +#define FAC_CODEUNI_ENUM 10 +#define FAC_CODEUNI_R11 11 +#define FAC_CODEUNI_R12 12 +#define FAC_CODEUNI_R13 13 +#define FAC_CODEUNI_R14 14 +#define FAC_CODEUNI_R15 15 +#define FAC_CODEUNI_SEQ 16 +#define FAC_CODEUNI_SET 17 +#define FAC_CODEUNI_NSTR 18 +#define FAC_CODEUNI_PSTR 19 +#define FAC_CODEUNI_TSTR 20 +#define FAC_CODEUNI_VSTR 21 +#define FAC_CODEUNI_ISTR 22 +#define FAC_CODEUNI_UTIME 23 +#define FAC_CODEUNI_GTIME 24 +#define FAC_CODEUNI_GSTR 25 +#define FAC_CODEUNI_VISTR 26 +#define FAC_CODEUNI_GNSTR 27 + +/* operation values */ +#define FAC_OPVAL_UUS 1 +#define FAC_OPVAL_CUG 2 +#define FAC_OPVAL_MCID 3 +#define FAC_OPVAL_BTPY 4 +#define FAC_OPVAL_ETPY 5 +#define FAC_OPVAL_ECT 6 + +#define FAC_OPVAL_DIV_ACT 7 +#define FAC_OPVAL_DIV_DEACT 8 +#define FAC_OPVAL_DIV_ACTSN 9 +#define FAC_OPVAL_DIV_DEACTSN 10 +#define FAC_OPVAL_DIV_INTER 11 +#define FAC_OPVAL_DIV_INFO 12 +#define FAC_OPVAL_DIV_CALLDEF 13 +#define FAC_OPVAL_DIV_CALLRER 14 +#define FAC_OPVAL_DIV_LINF2 15 +#define FAC_OPVAL_DIV_INVS 16 +#define FAC_OPVAL_DIV_INTER1 17 +#define FAC_OPVAL_DIV_LINF1 18 +#define FAC_OPVAL_DIV_LINF3 19 + +#define FAC_OPVAL_ER_CRCO 20 +#define FAC_OPVAL_ER_MGMT 21 +#define FAC_OPVAL_ER_CANC 22 + +#define FAC_OPVAL_MLPP_QUERY 24 +#define FAC_OPVAL_MLPP_CALLR 25 +#define FAC_OPVAL_MLPP_CALLP 26 + +#define FAC_OPVAL_AOC_REQ 30 +#define FAC_OPVAL_AOC_S_CUR 31 +#define FAC_OPVAL_AOC_S_SPC 32 +#define FAC_OPVAL_AOC_D_CUR 33 +#define FAC_OPVAL_AOC_D_UNIT 34 +#define FAC_OPVAL_AOC_E_CUR 35 +#define FAC_OPVAL_AOC_E_UNIT 36 +#define FAC_OPVAL_AOC_IDOFCRG 37 + +#define FAC_OPVAL_CONF_BEG 40 +#define FAC_OPVAL_CONF_ADD 41 +#define FAC_OPVAL_CONF_SPLIT 42 +#define FAC_OPVAL_CONF_DROP 43 +#define FAC_OPVAL_CONF_ISOLATE 44 +#define FAC_OPVAL_CONF_REATT 45 +#define FAC_OPVAL_CONF_PDISC 46 +#define FAC_OPVAL_CONF_FCONF 47 +#define FAC_OPVAL_CONF_END 48 +#define FAC_OPVAL_CONF_IDCFE 49 + +#define FAC_OPVAL_REVC_REQ 60 + +enum states { + ST_EXP_COMP_TYP, + ST_EXP_INV_ID, + ST_EXP_OP_VAL, + ST_EXP_INFO, + ST_EXP_RUL, + ST_EXP_RU, + ST_EXP_RNOU, + ST_EXP_TOCI, + ST_EXP_DBID, + + ST_EXP_NIX +}; + +/* EOF */ + diff --git a/sys/i4b/layer4/i4b_i4bdrv.c b/sys/i4b/layer4/i4b_i4bdrv.c new file mode 100644 index 0000000..0c21e8e --- /dev/null +++ b/sys/i4b/layer4/i4b_i4bdrv.c @@ -0,0 +1,832 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_i4bdrv.c - i4b userland interface driver + * -------------------------------------------- + * + * $Id: i4b_i4bdrv.c,v 1.33 1998/12/12 19:44:36 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:02 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" +#include "i4bipr.h" + +#if NI4B > 1 +#error "only 1 (one) i4b device possible!" +#endif + +#if NI4B > 0 + +#include <sys/param.h> + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#include <sys/malloc.h> +#include <sys/uio.h> +#else +#include <sys/ioctl.h> +#endif + +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <sys/select.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include "opt_devfs.h" +#endif + +#ifdef DEVFS +#include <sys/devfsext.h> +#endif + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer4/i4b_l4.h> + +#if defined(__FreeBSD__) && (!defined(__FreeBSD_version) || __FreeBSD_version < 300001) +/* do nothing */ +#else +#include <sys/poll.h> +#endif + +struct selinfo select_rd_info; + +static struct ifqueue i4b_rdqueue; +static int openflag = 0; +static int selflag = 0; +static int readflag = 0; +#ifdef DEVFS +static void *devfs_token; +#endif + +#ifndef __FreeBSD__ +#define PDEVSTATIC /* - not static - */ +PDEVSTATIC void i4battach __P((void)); +PDEVSTATIC int i4bopen __P((dev_t dev, int flag, int fmt, struct proc *p)); +PDEVSTATIC int i4bclose __P((dev_t dev, int flag, int fmt, struct proc *p)); +PDEVSTATIC int i4bread __P((dev_t dev, struct uio *uio, int ioflag)); +PDEVSTATIC int i4bioctl __P((dev_t dev, int cmd, caddr_t data, int flag, struct proc *p)); +PDEVSTATIC int i4bpoll __P((dev_t dev, int events, struct proc *p)); + +#if defined (__OpenBSD__) +PDEVSTATIC int i4bselect(dev_t dev, int rw, struct proc *p); +#endif + +#endif + +#if BSD > 199306 && defined(__FreeBSD__) +#define PDEVSTATIC static + +PDEVSTATIC d_open_t i4bopen; +PDEVSTATIC d_close_t i4bclose; +PDEVSTATIC d_read_t i4bread; +PDEVSTATIC d_ioctl_t i4bioctl; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +PDEVSTATIC d_poll_t i4bpoll; +#else +PDEVSTATIC d_select_t i4bselect; +#endif + +#define CDEV_MAJOR 60 +static struct cdevsw i4b_cdevsw = + { i4bopen, i4bclose, i4bread, nowrite, + i4bioctl, nostop, nullreset, nodevtotty, +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + i4bpoll, nommap, NULL, "i4b", NULL, -1 }; +#else + i4bselect, nommap, NULL, "i4b", NULL, -1 }; +#endif + +PDEVSTATIC void i4battach(void *); +PSEUDO_SET(i4battach, i4b_i4bdrv); + +#endif /* __FreeBSD__ */ + +/*---------------------------------------------------------------------------* + * interface attach routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC void +#ifdef __FreeBSD__ +i4battach(void *dummy) +#else +i4battach() +#endif +{ +#ifndef HACK_NO_PSEUDO_ATTACH_MSG + printf("i4b: ISDN call control device attached\n"); +#endif + i4b_rdqueue.ifq_maxlen = IFQ_MAXLEN; +#ifdef DEVFS + devfs_token = devfs_add_devswf(&i4b_cdevsw, 0, DV_CHR, + UID_ROOT, GID_WHEEL, 0600, + "i4b", 0); +#endif +} + +/*---------------------------------------------------------------------------* + * i4bopen - device driver open routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENXIO); + + if(openflag) + return(EBUSY); + + x = splimp(); + openflag = 1; + i4b_l4_daemon_attached(); + splx(x); + + return(0); +} + +/*---------------------------------------------------------------------------* + * i4bclose - device driver close routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + int x = splimp(); + openflag = 0; + i4b_l4_daemon_detached(); + i4b_Dcleanifq(&i4b_rdqueue); + splx(x); + return(0); +} + +/*---------------------------------------------------------------------------* + * i4bread - device driver read routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bread(dev_t dev, struct uio *uio, int ioflag) +{ + struct mbuf *m; + int x; + int error = 0; + + if(minor(dev)) + return(ENODEV); + + while(IF_QEMPTY(&i4b_rdqueue)) + { + x = splimp(); + readflag = 1; + splx(x); + tsleep((caddr_t) &i4b_rdqueue, (PZERO + 1) | PCATCH, "bird", 0); + } + + x = splimp(); + + IF_DEQUEUE(&i4b_rdqueue, m); + + splx(x); + + if(m && m->m_len) + error = uiomove(m->m_data, m->m_len, uio); + else + error = EIO; + + if(m) + i4b_Dfreembuf(m); + + return(error); +} + +/*---------------------------------------------------------------------------* + * i4bioctl - device driver ioctl routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +#if defined (__FreeBSD_version) && __FreeBSD_version >= 300003 +i4bioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +#else +i4bioctl(dev_t dev, int cmd, caddr_t data, int flag, struct proc *p) +#endif +{ + call_desc_t *cd; + int error = 0; + + if(minor(dev)) + return(ENODEV); + + switch(cmd) + { + /* cdid request, reserve cd and return cdid */ + + case I4B_CDID_REQ: + { + msg_cdid_req_t *mir; + mir = (msg_cdid_req_t *)data; + cd = reserve_cd(); + mir->cdid = cd->cdid; + break; + } + + /* connect request, dial out to remote */ + + case I4B_CONNECT_REQ: + { + msg_connect_req_t *mcr; + mcr = (msg_connect_req_t *)data; /* setup ptr */ + + if((cd = cd_by_cdid(mcr->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + cd->controller = mcr->controller; /* fill cd */ + cd->bprot = mcr->bprot; + cd->driver = mcr->driver; + cd->driver_unit = mcr->driver_unit; + cd->cr = get_rand_cr(ctrl_desc[cd->controller].unit); + + cd->unitlen_time = mcr->unitlen_time; + cd->idle_time = mcr->idle_time; + cd->earlyhup_time = mcr->earlyhup_time; + + cd->last_aocd_time = 0; + if(mcr->unitlen_method == ULEN_METHOD_DYNAMIC) + cd->aocd_flag = 1; + else + cd->aocd_flag = 0; + + cd->cunits = 0; + + cd->max_idle_time = 0; /* this is outgoing */ + + cd->dir = DIR_OUTGOING; + + DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_REQ times, unitlen=%ld idle=%ld earlyhup=%ld\n", + (long)cd->unitlen_time, (long)cd->idle_time, (long)cd->earlyhup_time)); + + strcpy(cd->dst_telno, mcr->dst_telno); + strcpy(cd->src_telno, mcr->src_telno); + cd->display[0] = '\0'; + + SET_CAUSE_TYPE(cd->cause_in, CAUSET_I4B); + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NORMAL); + + switch(mcr->channel) + { + case CHAN_B1: + case CHAN_B2: + if(ctrl_desc[mcr->controller].bch_state[mcr->channel] != BCH_ST_FREE) + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + + case CHAN_ANY: + if((ctrl_desc[mcr->controller].bch_state[CHAN_B1] != BCH_ST_FREE) && + (ctrl_desc[mcr->controller].bch_state[CHAN_B2] != BCH_ST_FREE)) + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + + default: + SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + break; + } + + cd->channelid = mcr->channel; + + cd->isdntxdelay = mcr->txdelay; + + /* check whether we have a pointer. Seems like */ + /* this should be adequate. GJ 19.09.97 */ + if(ctrl_desc[cd->controller].N_CONNECT_REQUEST == NULL) +/*XXX*/ SET_CAUSE_VAL(cd->cause_in, CAUSE_I4B_NOCHAN); + + if((GET_CAUSE_VAL(cd->cause_in)) != CAUSE_I4B_NORMAL) + { + i4b_l4_disconnect_ind(cd); + freecd_by_cd(cd); + } + else + { + (*ctrl_desc[cd->controller].N_CONNECT_REQUEST)(mcr->cdid); + } + break; + } + + /* connect response, accept/reject/ignore incoming call */ + + case I4B_CONNECT_RESP: + { + msg_connect_resp_t *mcrsp; + + mcrsp = (msg_connect_resp_t *)data; + + if((cd = cd_by_cdid(mcrsp->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_CONNECT_RESP ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + T400_stop(cd); + + cd->driver = mcrsp->driver; + cd->driver_unit = mcrsp->driver_unit; + cd->max_idle_time = mcrsp->max_idle_time; + + cd->unitlen_time = 0; /* this is incoming */ + cd->idle_time = 0; + cd->earlyhup_time = 0; + + cd->isdntxdelay = mcrsp->txdelay; + + DBGL4(L4_TIMO, "i4bioctl", ("I4B_CONNECT_RESP max_idle_time set to %ld seconds\n", (long)cd->max_idle_time)); + + (*ctrl_desc[cd->controller].N_CONNECT_RESPONSE)(mcrsp->cdid, mcrsp->response, mcrsp->cause); + break; + } + + /* disconnect request, actively terminate connection */ + + case I4B_DISCONNECT_REQ: + { + msg_discon_req_t *mdr; + + mdr = (msg_discon_req_t *)data; + + if((cd = cd_by_cdid(mdr->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_DISCONNECT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + /* preset causes with our cause */ + cd->cause_in = cd->cause_out = mdr->cause; + + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(mdr->cdid, mdr->cause); + break; + } + + /* controller info request */ + + case I4B_CTRL_INFO_REQ: + { + msg_ctrl_info_req_t *mcir; + + mcir = (msg_ctrl_info_req_t *)data; + mcir->ncontroller = nctrl; + + if(mcir->controller > nctrl) + { + mcir->ctrl_type = -1; + mcir->card_type = -1; + } + else + { + mcir->ctrl_type = + ctrl_desc[mcir->controller].ctrl_type; + mcir->card_type = + ctrl_desc[mcir->controller].card_type; + + if(ctrl_desc[mcir->controller].ctrl_type == CTRL_PASSIVE) + mcir->tei = ctrl_desc[mcir->controller].tei; + else + mcir->tei = -1; + } + break; + } + + /* dial response */ + + case I4B_DIALOUT_RESP: + { + msg_dialout_resp_t *mdrsp; + + mdrsp = (msg_dialout_resp_t *)data; + +#if NI4BIPR > 0 + if(mdrsp->driver == BDRV_IPR) + { + drvr_link_t *dlt; + dlt = ipr_ret_linktab(mdrsp->driver_unit); + (*dlt->dial_response)(mdrsp->driver_unit, mdrsp->stat); + } +#endif + break; + } + + /* update timeout value */ + + case I4B_TIMEOUT_UPD: + { + msg_timeout_upd_t *mtu; + int x; + + mtu = (msg_timeout_upd_t *)data; + + if((cd = cd_by_cdid(mtu->cdid)) == NULL)/* get cd */ + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_TIMEOUT_UPD ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + x = SPLI4B(); + cd->unitlen_time = mtu->unitlen_time; + cd->idle_time = mtu->idle_time; + cd->earlyhup_time = mtu->earlyhup_time; + splx(x); + break; + } + + /* soft enable/disable interface */ + + case I4B_UPDOWN_IND: + { + msg_updown_ind_t *mui; + + mui = (msg_updown_ind_t *)data; + +#if NI4BIPR > 0 + if(mui->driver == BDRV_IPR) + { + drvr_link_t *dlt; + dlt = ipr_ret_linktab(mui->driver_unit); + (*dlt->updown_ind)(mui->driver_unit, mui->updown); + } +#endif + break; + } + + /* send ALERT request */ + + case I4B_ALERT_REQ: + { + msg_alert_req_t *mar; + + mar = (msg_alert_req_t *)data; + + if((cd = cd_by_cdid(mar->cdid)) == NULL) + { + DBGL4(L4_ERR, "i4bioctl", ("I4B_ALERT_REQ ioctl, cdid not found!\n")); + error = EINVAL; + break; + } + + T400_stop(cd); + + (*ctrl_desc[cd->controller].N_ALERT_REQUEST)(mar->cdid); + + break; + } + + /* version/release number request */ + + case I4B_VR_REQ: + { + msg_vr_req_t *mvr; + + mvr = (msg_vr_req_t *)data; + + mvr->version = VERSION; + mvr->release = REL; + mvr->step = STEP; + break; + } + + /* Download request */ + + case I4B_CTRL_DOWNLOAD: + { + struct isdn_dr_prot *prots = NULL, *prots2 = NULL; + struct isdn_download_request *r = + (struct isdn_download_request*)data; + int i; + + if(!ctrl_desc[r->controller].N_DOWNLOAD) + { + error = ENODEV; + goto download_done; + } + + prots = malloc(r->numprotos * sizeof(struct isdn_dr_prot), + M_DEVBUF, M_WAITOK); + + prots2 = malloc(r->numprotos * sizeof(struct isdn_dr_prot), + M_DEVBUF, M_WAITOK); + + if(!prots || !prots2) + { + error = ENOMEM; + goto download_done; + } + + copyin(r->protocols, prots, r->numprotos * sizeof(struct isdn_dr_prot)); + + for(i = 0; i < r->numprotos; i++) + { + prots2[i].microcode = malloc(prots[i].bytecount, M_DEVBUF, M_WAITOK); + copyin(prots[i].microcode, prots2[i].microcode, prots[i].bytecount); + prots2[i].bytecount = prots[i].bytecount; + } + + error = ctrl_desc[r->controller].N_DOWNLOAD( + ctrl_desc[r->controller].unit, + r->numprotos, prots2); + +download_done: + if(prots2) + { + for(i = 0; i < r->numprotos; i++) + { + if(prots2[i].microcode) + { + free(prots2[i].microcode, M_DEVBUF); + } + } + free(prots2, M_DEVBUF); + } + + if(prots) + { + free(prots, M_DEVBUF); + } + break; + } + + /* Diagnostic request */ + + case I4B_ACTIVE_DIAGNOSTIC: + { + struct isdn_diagnostic_request req, *r = + (struct isdn_diagnostic_request*)data; + + req.in_param = req.out_param = NULL; + + if(!ctrl_desc[r->controller].N_DIAGNOSTICS) + { + error = ENODEV; + goto diag_done; + } + + memcpy(&req, r, sizeof(req)); + + if(req.in_param_len) + { + req.in_param = malloc(r->in_param_len, M_DEVBUF, M_WAITOK); + + if(!req.in_param) + { + error = ENOMEM; + goto diag_done; + } + copyin(r->in_param, req.in_param, req.in_param_len); + } + + if(req.out_param_len) + { + req.out_param = malloc(r->out_param_len, M_DEVBUF, M_WAITOK); + + if(!req.out_param) + { + error = ENOMEM; + goto diag_done; + } + } + + error = ctrl_desc[r->controller].N_DIAGNOSTICS(r->controller, &req); + + if(!error && req.out_param_len) + copyout(req.out_param, r->out_param, req.out_param_len); + +diag_done: + if(req.in_param) + free(req.in_param, M_DEVBUF); + + if(req.out_param) + free(req.out_param, M_DEVBUF); + + break; + } + + /* default */ + + default: + error = ENOTTY; + break; + } + + return(error); +} + +#if (defined(__FreeBSD__) && \ + (!defined(__FreeBSD_version) || (__FreeBSD_version < 300001))) \ + || defined (__OpenBSD__) + +/*---------------------------------------------------------------------------* + * i4bselect - device driver select routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bselect(dev_t dev, int rw, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENODEV); + + switch(rw) + { + case FREAD: + if(!IF_QEMPTY(&i4b_rdqueue)) + return(1); + x = splimp(); + selrecord(p, &select_rd_info); + selflag = 1; + splx(x); + return(0); + break; + + case FWRITE: + return(1); + break; + } + return(0); +} + +#else /* NetBSD and FreeBSD -current */ + +/*---------------------------------------------------------------------------* + * i4bpoll - device driver poll routine + *---------------------------------------------------------------------------*/ +PDEVSTATIC int +i4bpoll(dev_t dev, int events, struct proc *p) +{ + int x; + + if(minor(dev)) + return(ENODEV); + + if((events & POLLIN) || (events & POLLRDNORM)) + { + if(!IF_QEMPTY(&i4b_rdqueue)) + return(1); + + x = splimp(); + selrecord(p, &select_rd_info); + selflag = 1; + splx(x); + return(0); + } + else if((events & POLLOUT) || (events & POLLWRNORM)) + { + return(1); + } + + return(0); +} + +#endif /* defined(__FreeBSD__) && __FreeBSD__ < 3 */ + +/*---------------------------------------------------------------------------* + * i4bputqueue - put message into queue to userland + *---------------------------------------------------------------------------*/ +void +i4bputqueue(struct mbuf *m) +{ + int x; + + if(!openflag) + { + i4b_Dfreembuf(m); + return; + } + + x = splimp(); + + if(IF_QFULL(&i4b_rdqueue)) + { + struct mbuf *m1; + IF_DEQUEUE(&i4b_rdqueue, m1); + i4b_Dfreembuf(m1); + DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n")); + } + + IF_ENQUEUE(&i4b_rdqueue, m); + + splx(x); + + if(readflag) + { + readflag = 0; + wakeup((caddr_t) &i4b_rdqueue); + } + + if(selflag) + { + selflag = 0; + selwakeup(&select_rd_info); + } +} + +/*---------------------------------------------------------------------------* + * i4bputqueue_hipri - put message into front of queue to userland + *---------------------------------------------------------------------------*/ +void +i4bputqueue_hipri(struct mbuf *m) +{ + int x; + + if(!openflag) + { + i4b_Dfreembuf(m); + return; + } + + x = splimp(); + + if(IF_QFULL(&i4b_rdqueue)) + { + struct mbuf *m1; + IF_DEQUEUE(&i4b_rdqueue, m1); + i4b_Dfreembuf(m1); + DBGL4(L4_ERR, "i4bputqueue", ("ERROR, queue full, removing entry!\n")); + } + + IF_PREPEND(&i4b_rdqueue, m); + + splx(x); + + if(readflag) + { + readflag = 0; + wakeup((caddr_t) &i4b_rdqueue); + } + + if(selflag) + { + selflag = 0; + selwakeup(&select_rd_info); + } +} + +#if BSD > 199306 && defined(__FreeBSD__) +static i4b_devsw_installed = 0; + +static void +i4b_drvinit(void *unused) +{ + dev_t dev; + + if( ! i4b_devsw_installed ) { + dev = makedev(CDEV_MAJOR,0); + cdevsw_add(&dev,&i4b_cdevsw,NULL); + i4b_devsw_installed = 1; + } +} + +SYSINIT(i4bdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,i4b_drvinit,NULL) +#endif /* __FreeBSD__ */ +#endif /* NI4B > 0 */ diff --git a/sys/i4b/layer4/i4b_l4.c b/sys/i4b/layer4/i4b_l4.c new file mode 100644 index 0000000..cecd5f4 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4.c @@ -0,0 +1,897 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4.c - kernel interface to userland + * ----------------------------------------- + * + * $Id: i4b_l4.c,v 1.33 1998/12/05 18:05:49 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:16 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" +#include "i4bipr.h" +#include "i4bisppp.h" +#include "i4brbch.h" +#include "i4btel.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#include <i4b/i4b_cause.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/layer3/i4b_l3.h> +#include <i4b/layer4/i4b_l4.h> + +unsigned int i4b_l4_debug = L4_DEBUG_DEFAULT; + +struct ctrl_type_desc ctrl_types[CTRL_NUMTYPES] = { { NULL, NULL} }; + +static int i4b_link_bchandrvr(call_desc_t *cd); +static void i4b_unlink_bchandrvr(call_desc_t *cd); +static void i4b_l4_setup_timeout(call_desc_t *cd); + +/*---------------------------------------------------------------------------* + * send MSG_PDEACT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_pdeact(int controller, int numactive) +{ + struct mbuf *m; + int i; + call_desc_t *cd; + + for(i=0; i < N_CALL_DESC; i++) + { + if((call_desc[i].cdid != CDID_UNUSED) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == controller)) + { + cd = &call_desc[i]; + + if(cd->timeout_active) + { +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, cd->idle_timeout_handle); +#else + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd); +#endif + } + + if(cd->dlt != NULL) + { + (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); + i4b_unlink_bchandrvr(cd); + } + + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; + } + + cd->cdid = CDID_UNUSED; + } + } + + if((m = i4b_Dgetmbuf(sizeof(msg_pdeact_ind_t))) != NULL) + { + msg_pdeact_ind_t *md = (msg_pdeact_ind_t *)m->m_data; + + md->header.type = MSG_PDEACT_IND; + md->header.cdid = -1; + + md->controller = controller; + md->numactive = numactive; + + i4bputqueue_hipri(m); /* URGENT !!! */ + } +} + +/*---------------------------------------------------------------------------* + * send MSG_L12STAT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_l12stat(int controller, int layer, int state) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_l12stat_ind_t))) != NULL) + { + msg_l12stat_ind_t *md = (msg_l12stat_ind_t *)m->m_data; + + md->header.type = MSG_L12STAT_IND; + md->header.cdid = -1; + + md->controller = controller; + md->layer = layer; + md->state = state; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_TEIASG_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_teiasg(int controller, int tei) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_teiasg_ind_t))) != NULL) + { + msg_teiasg_ind_t *md = (msg_teiasg_ind_t *)m->m_data; + + md->header.type = MSG_TEIASG_IND; + md->header.cdid = -1; + + md->controller = controller; + md->tei = ctrl_desc[controller].tei; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DIALOUT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_dialout(int driver, int driver_unit) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_dialout_ind_t))) != NULL) + { + msg_dialout_ind_t *md = (msg_dialout_ind_t *)m->m_data; + + md->header.type = MSG_DIALOUT_IND; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_NEGOTIATION_COMPL message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_negcomplete(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_negcomplete_ind_t))) != NULL) + { + msg_negcomplete_ind_t *md = (msg_negcomplete_ind_t *)m->m_data; + + md->header.type = MSG_NEGCOMP_IND; + md->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_IFSTATE_CHANGED_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_ifstate_changed(call_desc_t *cd, int new_state) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_ifstatechg_ind_t))) != NULL) + { + msg_ifstatechg_ind_t *md = (msg_ifstatechg_ind_t *)m->m_data; + + md->header.type = MSG_IFSTATE_CHANGED_IND; + md->header.cdid = cd->cdid; + md->state = new_state; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DRVRDISC_REQ message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_drvrdisc(int driver, int driver_unit) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_drvrdisc_req_t))) != NULL) + { + msg_drvrdisc_req_t *md = (msg_drvrdisc_req_t *)m->m_data; + + md->header.type = MSG_DRVRDISC_REQ; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_ACCT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_accounting(int driver, int driver_unit, int accttype, int ioutbytes, + int iinbytes, int ro, int ri, int outbytes, int inbytes) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_accounting_ind_t))) != NULL) + { + msg_accounting_ind_t *md = (msg_accounting_ind_t *)m->m_data; + + md->header.type = MSG_ACCT_IND; + md->header.cdid = -1; + + md->driver = driver; + md->driver_unit = driver_unit; + + md->accttype = accttype; + md->ioutbytes = ioutbytes; + md->iinbytes = iinbytes; + md->outbps = ro; + md->inbps = ri; + md->outbytes = outbytes; + md->inbytes = inbytes; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CONNECT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_connect_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_connect_ind_t))) != NULL) + { + msg_connect_ind_t *mp = (msg_connect_ind_t *)m->m_data; + + mp->header.type = MSG_CONNECT_IND; + mp->header.cdid = cd->cdid; + + mp->controller = cd->controller; + mp->channel = cd->channelid; + mp->bprot = cd->bprot; + + cd->dir = DIR_INCOMING; + + if(strlen(cd->dst_telno) > 0) + strcpy(mp->dst_telno, cd->dst_telno); + else + strcpy(mp->dst_telno, TELNO_EMPTY); + + if(strlen(cd->src_telno) > 0) + strcpy(mp->src_telno, cd->src_telno); + else + strcpy(mp->src_telno, TELNO_EMPTY); + + strcpy(mp->display, cd->display); + + mp->scr_ind = cd->scr_ind; + + T400_start(cd); + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CONNECT_ACTIVE_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_connect_active_ind(call_desc_t *cd) +{ + int s; + struct mbuf *m; + + s = SPLI4B(); + + cd->last_active_time = cd->connect_time = SECOND; + + DBGL4(L4_TIMO, "i4b_l4_connect_active_ind", ("last_active/connect_time=%ld\n", (long)cd->connect_time)); + + i4b_link_bchandrvr(cd); + + (*cd->dlt->line_connected)(cd->driver_unit, (void *)cd); + + i4b_l4_setup_timeout(cd); + + splx(s); + + if((m = i4b_Dgetmbuf(sizeof(msg_connect_active_ind_t))) != NULL) + { + msg_connect_active_ind_t *mp = (msg_connect_active_ind_t *)m->m_data; + + mp->header.type = MSG_CONNECT_ACTIVE_IND; + mp->header.cdid = cd->cdid; + mp->controller = cd->controller; + mp->channel = cd->channelid; + if(cd->datetime[0] != '\0') + strcpy(mp->datetime, cd->datetime); + else + mp->datetime[0] = '\0'; + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_DISCONNECT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_disconnect_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if(cd->timeout_active) +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, cd->idle_timeout_handle); +#else + untimeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd); +#endif + + if(cd->dlt != NULL) + { + (*cd->dlt->line_disconnected)(cd->driver_unit, (void *)cd); + i4b_unlink_bchandrvr(cd); + } + + if((cd->channelid == CHAN_B1) || (cd->channelid == CHAN_B2)) + { + ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_FREE; + } + else + { + /* no error, might be hunting call for callback */ + DBGL4(L4_MSG, "i4b_l4_disconnect_ind", ("channel free not B1/B2 but %d!\n", cd->channelid)); + } + + if((m = i4b_Dgetmbuf(sizeof(msg_disconnect_ind_t))) != NULL) + { + msg_disconnect_ind_t *mp = (msg_disconnect_ind_t *)m->m_data; + + mp->header.type = MSG_DISCONNECT_IND; + mp->header.cdid = cd->cdid; + mp->cause = cd->cause_in; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_IDLE_TIMEOUT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_idle_timeout_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_idle_timeout_ind_t))) != NULL) + { + msg_idle_timeout_ind_t *mp = (msg_idle_timeout_ind_t *)m->m_data; + + mp->header.type = MSG_IDLE_TIMEOUT_IND; + mp->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_CHARGING_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_charging_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_charging_ind_t))) != NULL) + { + msg_charging_ind_t *mp = (msg_charging_ind_t *)m->m_data; + + mp->header.type = MSG_CHARGING_IND; + mp->header.cdid = cd->cdid; + mp->units_type = cd->units_type; + +/*XXX*/ if(mp->units_type == CHARGE_CALC) + mp->units = cd->cunits; + else + mp->units = cd->units; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_STATUS_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_status_ind(call_desc_t *cd) +{ +} + +/*---------------------------------------------------------------------------* + * send MSG_ALERT_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_alert_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_alert_ind_t))) != NULL) + { + msg_alert_ind_t *mp = (msg_alert_ind_t *)m->m_data; + + mp->header.type = MSG_ALERT_IND; + mp->header.cdid = cd->cdid; + + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * send MSG_INFO_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_info_ind(call_desc_t *cd) +{ +} + +/*---------------------------------------------------------------------------* + * send MSG_INFO_IND message to userland + *---------------------------------------------------------------------------*/ +void +i4b_l4_proceeding_ind(call_desc_t *cd) +{ + struct mbuf *m; + + if((m = i4b_Dgetmbuf(sizeof(msg_proceeding_ind_t))) != NULL) + { + msg_proceeding_ind_t *mp = (msg_proceeding_ind_t *)m->m_data; + + mp->header.type = MSG_PROCEEDING_IND; + mp->header.cdid = cd->cdid; + mp->controller = cd->controller; + mp->channel = cd->channelid; + i4bputqueue(m); + } +} + +/*---------------------------------------------------------------------------* + * link a driver(unit) to a B-channel(controller,unit,channel) + *---------------------------------------------------------------------------*/ +static int +i4b_link_bchandrvr(call_desc_t *cd) +{ + int t = ctrl_desc[cd->controller].ctrl_type; + + if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL) + { + cd->ilt = NULL; + } + else + { + cd->ilt = ctrl_types[t].get_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid); + } + + switch(cd->driver) + { +#if NI4BRBCH > 0 + case BDRV_RBCH: + cd->dlt = rbch_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BTEL > 0 + case BDRV_TEL: + cd->dlt = tel_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BIPR > 0 + case BDRV_IPR: + cd->dlt = ipr_ret_linktab(cd->driver_unit); + break; +#endif + +#if NI4BISPPP > 0 + case BDRV_ISPPP: + cd->dlt = i4bisppp_ret_linktab(cd->driver_unit); + break; +#endif + + default: + cd->dlt = NULL; + break; + } + + if(cd->dlt == NULL || cd->ilt == NULL) + return(-1); + + if(t >= 0 && t < CTRL_NUMTYPES && ctrl_types[t].set_linktab != NULL) + { + ctrl_types[t].set_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid, + cd->dlt); + } + + switch(cd->driver) + { +#if NI4BRBCH > 0 + case BDRV_RBCH: + rbch_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BTEL > 0 + case BDRV_TEL: + tel_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BIPR > 0 + case BDRV_IPR: + ipr_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + +#if NI4BISPPP > 0 + case BDRV_ISPPP: + i4bisppp_set_linktab(cd->driver_unit, cd->ilt); + break; +#endif + default: + return(0); + break; + } + + /* activate B channel */ + + (*cd->ilt->bch_config)(ctrl_desc[cd->controller].unit, + cd->channelid, cd->bprot, 1); + + return(0); +} + +/*---------------------------------------------------------------------------* + * unlink a driver(unit) from a B-channel(controller,unit,channel) + *---------------------------------------------------------------------------*/ +static void +i4b_unlink_bchandrvr(call_desc_t *cd) +{ + int t = ctrl_desc[cd->controller].ctrl_type; + + if(t < 0 || t >= CTRL_NUMTYPES || ctrl_types[t].get_linktab == NULL) + { + cd->ilt = NULL; + return; + } + else + { + cd->ilt = ctrl_types[t].get_linktab( + ctrl_desc[cd->controller].unit, + cd->channelid); + } + + /* deactivate B channel */ + + (*cd->ilt->bch_config)(ctrl_desc[cd->controller].unit, + cd->channelid, cd->bprot, 0); +} + +/*--------------------------------------------------------------------------- + + How shorthold mode works for OUTGOING connections + ================================================= + + |<---- unchecked-window ------->|<-checkwindow->|<-safetywindow>| + +idletime_state: IST_NONCHK IST_CHECK IST_SAFE + + | | | | + time>>+-------------------------------+---------------+---------------+-... + | | | | + | |<--idle_time-->|<--earlyhup--->| + |<-----------------------unitlen------------------------------->| + + + unitlen - specifies the time a charging unit lasts + idle_time - specifies the thime the line must be idle at the + end of the unit to be elected for hangup + earlyhup - is the beginning of a timing safety zone before the + next charging unit starts + + The algorithm works as follows: lets assume the unitlen is 100 + secons, idle_time is 40 seconds and earlyhup is 10 seconds. + The line then must be idle 50 seconds after the begin of the + current unit and it must then be quiet for 40 seconds. if it + has been quiet for this 40 seconds, the line is closed 10 + seconds before the next charging unit starts. In case there was + any traffic within the idle_time, the line is not closed. + It does not matter whether there was any traffic between second + 0 and second 50 or not. + + + How shorthold mode works for INCOMING connections + ================================================= + + it is just possible to specify a maximum idle time for incoming + connections, after this time of no activity on the line the line + is closed. + +---------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------* + * B channel idle check timeout setup + *---------------------------------------------------------------------------*/ +static void +i4b_l4_setup_timeout(call_desc_t *cd) +{ + cd->timeout_active = 0; + cd->idletime_state = IST_IDLE; + + if((cd->dir == DIR_INCOMING) && (cd->max_idle_time > 0)) + { + /* incoming call: simple max idletime check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: incoming-call, setup max_idle_time to %ld\n", (long)SECOND, (long)cd->max_idle_time)); + } + else if((cd->dir == DIR_OUTGOING) && (cd->idle_time > 0)) + { + /* outgoing call */ + + if((cd->idle_time > 0) && (cd->unitlen_time == 0)) + { + /* outgoing call: simple max idletime check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: outgoing-call, setup idle_time to %ld\n", (long)SECOND, (long)cd->idle_time)); + } + else if((cd->unitlen_time > 0) && (cd->unitlen_time > (cd->idle_time + cd->earlyhup_time))) + { + /* outgoing call: full shorthold mode check */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->unitlen_time - (cd->idle_time + cd->earlyhup_time))); + cd->timeout_active = 1; + cd->idletime_state = IST_NONCHK; + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("%ld: outgoing-call, start %ld sec nocheck window\n", + (long)SECOND, (long)(cd->unitlen_time - (cd->idle_time + cd->earlyhup_time)))); + + if(cd->aocd_flag == 0) + { + cd->units_type = CHARGE_CALC; + cd->cunits++; + i4b_l4_charging_ind(cd); + } + } + else + { + /* parms somehow got wrong .. */ + + DBGL4(L4_ERR, "i4b_l4_setup_timeout", ("%ld: ERROR: idletime[%ld]+earlyhup[%ld] > unitlength[%ld]!\n", + (long)SECOND, (long)cd->idle_time, (long)cd->earlyhup_time, (long)cd->unitlen_time)); + } + } + else + { + DBGL4(L4_TIMO, "i4b_l4_setup_timeout", ("no idle_timeout configured\n")); + } +} + +/*---------------------------------------------------------------------------* + * B channel idle check timeout function + *---------------------------------------------------------------------------*/ +void +i4b_idle_check(call_desc_t *cd) +{ + int s; + + if(cd->cdid == CDID_UNUSED) + return; + + s = SPLI4B(); + + /* failsafe */ + + if(cd->timeout_active == 0) + { + DBGL4(L4_ERR, "i4b_idle_check", ("ERROR: timeout_active == 0 !!!\n")); + } + else + { + cd->timeout_active = 0; + } + + /* incoming connections, simple idletime check */ + + if(cd->dir == DIR_INCOMING) + { + if((cd->last_active_time + cd->max_idle_time) <= SECOND) + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: incoming-call, line idle timeout, disconnecting!\n", (long)SECOND)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + } + else + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: incoming-call, activity, last_active=%ld, max_idle=%ld\n", (long)SECOND, (long)cd->last_active_time, (long)cd->max_idle_time)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + } + } + + /* outgoing connections */ + + else if(cd->dir == DIR_OUTGOING) + { + + /* simple idletime calculation */ + + if((cd->idle_time > 0) && (cd->unitlen_time == 0)) + { + if((cd->last_active_time + cd->idle_time) <= SECOND) + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call-st, idle timeout, disconnecting!\n", (long)SECOND)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + } + else + { + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call-st, activity, last_active=%ld, max_idle=%ld\n", + (long)SECOND, (long)cd->last_active_time, (long)cd->idle_time)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz/2); + cd->timeout_active = 1; + } + } + + /* full shorthold mode calculation */ + + else if((cd->unitlen_time > 0) && (cd->unitlen_time > (cd->idle_time + cd->earlyhup_time))) + { + switch(cd->idletime_state) + { + case IST_NONCHK: /* end of non-check time */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->idle_time)); + cd->idletimechk_start = SECOND; + cd->idletime_state = IST_CHECK; + cd->timeout_active = 1; + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, idletime check window reached!\n", (long)SECOND)); + break; + + case IST_CHECK: /* end of idletime chk */ + if((cd->last_active_time > cd->idletimechk_start) && + (cd->last_active_time <= SECOND)) + { /* activity detected */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->earlyhup_time)); + cd->timeout_active = 1; + cd->idletime_state = IST_SAFE; + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, activity at %ld, wait earlyhup-end\n", (long)SECOND, (long)cd->last_active_time)); + } + else + { /* no activity, hangup */ + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, idle timeout, last activity at %ld\n", (long)SECOND, (long)cd->last_active_time)); + (*ctrl_desc[cd->controller].N_DISCONNECT_REQUEST)(cd->cdid, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + i4b_l4_idle_timeout_ind(cd); + cd->idletime_state = IST_IDLE; + } + break; + + case IST_SAFE: /* end of earlyhup time */ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->idle_timeout_handle = +#endif + timeout((TIMEOUT_FUNC_T)i4b_idle_check,(void *)cd, hz*(cd->unitlen_time - (cd->idle_time+cd->earlyhup_time))); + cd->timeout_active = 1; + cd->idletime_state = IST_NONCHK; + + if(cd->aocd_flag == 0) + { + cd->units_type = CHARGE_CALC; + cd->cunits++; + i4b_l4_charging_ind(cd); + } + + DBGL4(L4_TIMO, "i4b_idle_check", ("%ld: outgoing-call, earlyhup end, wait for idletime start\n", (long)SECOND)); + break; + + default: + DBGL4(L4_ERR, "i4b_idle_check", ("outgoing-call: invalid idletime_state value!\n")); + cd->idletime_state = IST_IDLE; + break; + } + } + } + splx(s); +} + +#endif /* NI4B > 0 */ diff --git a/sys/i4b/layer4/i4b_l4.h b/sys/i4b/layer4/i4b_l4.h new file mode 100644 index 0000000..e4ed863f --- /dev/null +++ b/sys/i4b/layer4/i4b_l4.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4.h - kernel interface to userland header file + * --------------------------------------------------- + * + * $Id: i4b_l4.h,v 1.13 1998/12/05 18:05:50 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:34 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_L4_H_ +#define _I4B_L4_H_ + +extern void i4bputqueue ( struct mbuf *m ); +extern void i4bputqueue_hipri(struct mbuf *m); +extern void i4b_l4_accounting(int, int, int, int, int, int, int, int, int); +extern void i4b_l4_alert_ind ( call_desc_t *cd ); +extern void i4b_l4_charging_ind( call_desc_t *cd ); +extern void i4b_l4_connect_active_ind ( call_desc_t *cd ); +extern void i4b_l4_connect_ind ( call_desc_t *cd ); +extern void i4b_l4_daemon_attached(void); +extern void i4b_l4_daemon_detached(void); +extern void i4b_l4_dialout( int driver, int driver_unit ); +extern void i4b_l4_disconnect_ind ( call_desc_t *cd ); +extern void i4b_l4_drvrdisc (int driver, int driver_unit ); +extern void i4b_l4_negcomplete( call_desc_t *cd ); +extern void i4b_l4_ifstate_changed( call_desc_t *cd, int new_state ); +extern void i4b_l4_idle_timeout_ind( call_desc_t *cd ); +extern void i4b_l4_info_ind ( call_desc_t *cd ); +extern void i4b_l4_l12stat(int controller, int layer, int state); +extern void i4b_l4_pdeact(int controller, int numactive); +extern void i4b_l4_teiasg(int controller, int tei); +extern void i4b_l4_status_ind ( call_desc_t *cd ); +extern void i4b_l4_proceeding_ind ( call_desc_t *cd ); +extern void i4b_idle_check(call_desc_t *cdp); +extern call_desc_t * cd_by_cdid ( unsigned int cdid ); +extern call_desc_t * cd_by_unitcr ( int unit, int cr, int crf ); +extern void freecd_by_cd ( call_desc_t *cd ); +extern unsigned char get_rand_cr ( int unit ); +extern call_desc_t * reserve_cd ( void ); +extern void T400_start ( call_desc_t *cd ); +extern void T400_stop ( call_desc_t *cd ); + +#endif /* _I4B_L4_H_ */ diff --git a/sys/i4b/layer4/i4b_l4mgmt.c b/sys/i4b/layer4/i4b_l4mgmt.c new file mode 100644 index 0000000..e8e1a96 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4mgmt.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4mgmt.c - layer 4 calldescriptor management utilites + * ----------------------------------------------------------- + * + * $Id: i4b_l4mgmt.c,v 1.23 1998/12/05 18:05:52 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:35:50 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <machine/random.h> +#endif +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_l2l3.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> +#include <i4b/include/i4b_isdnq931.h> +#include <i4b/include/i4b_global.h> + +#include <i4b/layer4/i4b_l4.h> + +call_desc_t call_desc[N_CALL_DESC]; /* call descriptor array */ + +static unsigned int get_cdid(void); + +int nctrl; /* number of attached controllers */ + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +void init_callout(call_desc_t *); +#endif + +/*---------------------------------------------------------------------------* + * return a new unique call descriptor id + * -------------------------------------- + * returns a new calldescriptor id which is used to uniquely identyfy + * a single call in the communication between kernel and userland. + * this cdid is then used to associate a calldescriptor with an id. + *---------------------------------------------------------------------------*/ +static unsigned int +get_cdid(void) +{ + static unsigned int cdid_count = 0; + int i; + int x; + + x = SPLI4B(); + + /* get next id */ + + cdid_count++; + +again: + if(cdid_count == CDID_UNUSED) /* zero is invalid */ + cdid_count++; + else if(cdid_count > CDID_MAX) /* wraparound ? */ + cdid_count = 1; + + /* check if id already in use */ + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == cdid_count) + { + cdid_count++; + goto again; + } + } + + splx(x); + + return(cdid_count); +} + +/*---------------------------------------------------------------------------* + * reserve a calldescriptor for later usage + * ---------------------------------------- + * searches the calldescriptor array until an unused + * descriptor is found, gets a new calldescriptor id + * and reserves it by putting the id into the cdid field. + * returns pointer to the calldescriptor. + *---------------------------------------------------------------------------*/ +call_desc_t * +reserve_cd(void) +{ + call_desc_t *cd; + int x; + int i; + + x = SPLI4B(); + + cd = NULL; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == CDID_UNUSED) + { + bzero(&call_desc[i], sizeof(call_desc_t)); /* clear it */ + call_desc[i].cdid = get_cdid(); /* fill in new cdid */ + cd = &(call_desc[i]); /* get pointer to descriptor */ + DBGL4(L4_MSG, "reserve_cd", ("found free cd - index=%d cdid=%u\n", + i, call_desc[i].cdid)); + break; + } + } + + splx(x); + + if(cd == NULL) + panic("reserve_cd: no free call descriptor available!"); + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(cd); +#endif + + return(cd); +} + +/*---------------------------------------------------------------------------* + * free a calldescriptor + * --------------------- + * free a unused calldescriptor by giving address of calldescriptor + * and writing a 0 into the cdid field marking it as unused. + *---------------------------------------------------------------------------*/ +void +freecd_by_cd(call_desc_t *cd) +{ + int i; + int x = SPLI4B(); + + for(i=0; i < N_CALL_DESC; i++) + { + if( (call_desc[i].cdid != CDID_UNUSED) && + (&(call_desc[i]) == cd) ) + { + DBGL4(L4_MSG, "freecd_by_cd", ("releasing cd - index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, cd->cr)); + call_desc[i].cdid = CDID_UNUSED; + break; + } + } + + if(i == N_CALL_DESC) + panic("freecd_by_cd: ERROR, cd not found, cr = %d\n", cd->cr); + + splx(x); +} + +/*---------------------------------------------------------------------------* + * return pointer to calldescriptor by giving the calldescriptor id + * ---------------------------------------------------------------- + * lookup a calldescriptor in the calldescriptor array by looking + * at the cdid field. return pointer to calldescriptor if found, + * else return NULL if not found. + *---------------------------------------------------------------------------*/ +call_desc_t * +cd_by_cdid(unsigned int cdid) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid == cdid) + { + DBGL4(L4_MSG, "cd_by_cdid", ("found cdid - index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, call_desc[i].cr)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(&call_desc[i]); +#endif + return(&(call_desc[i])); + } + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * search calldescriptor + * --------------------- + * This routine searches for the calldescriptor for a passive controller + * given by unit number, callreference and callreference flag. + * It returns a pointer to the calldescriptor if found, else a NULL. + *---------------------------------------------------------------------------*/ +call_desc_t * +cd_by_unitcr(int unit, int cr, int crf) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if((call_desc[i].cdid != CDID_UNUSED) && + (ctrl_desc[call_desc[i].controller].ctrl_type == CTRL_PASSIVE) && + (ctrl_desc[call_desc[i].controller].unit == unit) && + (call_desc[i].cr == cr) && + (call_desc[i].crflag == crf) ) + { + DBGL4(L4_MSG, "cd_by_unitcr", ("found cd, index=%d cdid=%u cr=%d\n", + i, call_desc[i].cdid, call_desc[i].cr)); +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + init_callout(&call_desc[i]); +#endif + return(&(call_desc[i])); + } + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * generate 7 bit "random" number used for outgoing Call Reference + *---------------------------------------------------------------------------*/ +unsigned char +get_rand_cr(int unit) +{ + register int i, j; + static u_char val, retval; + static int called = 42; + + val += ++called; + + for(i=0; i < 50 ; i++, val++) + { + int found = 1; + +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + read_random((char *)&val, sizeof(val)); +#else + val |= unit+i; + val <<= i; + val ^= (time.tv_sec >> 8) ^ time.tv_usec; + val <<= i; + val ^= time.tv_sec ^ (time.tv_usec >> 8); +#endif + + retval = val & 0x7f; + + if(retval == 0 || retval == 0x7f) + continue; + + for(j=0; j < N_CALL_DESC; j++) + { + if( (call_desc[j].cdid != CDID_UNUSED) && + (call_desc[j].cr == retval) ) + { + found = 0; + break; + } + } + + if(found) + return(retval); + } + return(0); /* XXX */ +} + +/*---------------------------------------------------------------------------* + * initialize the callout handles for FreeBSD-current 3.0 + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +void +init_callout(call_desc_t *cd) +{ + if(cd->callouts_inited == 0) + { + callout_handle_init(&cd->idle_timeout_handle); + callout_handle_init(&cd->T303_callout); + callout_handle_init(&cd->T305_callout); + callout_handle_init(&cd->T308_callout); + callout_handle_init(&cd->T309_callout); + callout_handle_init(&cd->T310_callout); + callout_handle_init(&cd->T313_callout); + callout_handle_init(&cd->T400_callout); + cd->callouts_inited = 1; + } +} +#endif + +/*---------------------------------------------------------------------------* + * daemon is attached + *---------------------------------------------------------------------------*/ +void +i4b_l4_daemon_attached(void) +{ + int i; + + int x = SPLI4B(); + + for(i=0; i < nctrl; i++) + { +/*XXX*/ if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE) + { + DBGL4(L4_MSG, "i4b_l4_daemon_attached", ("CMR_DOPEN sent to unit %d\n", ctrl_desc[i].unit)); + + (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DOPEN, 0); + } + } + splx(x); +} + +/*---------------------------------------------------------------------------* + * daemon is detached + *---------------------------------------------------------------------------*/ +void +i4b_l4_daemon_detached(void) +{ + int i; + + int x = SPLI4B(); + + for(i=0; i < nctrl; i++) + { +/*XXX*/ if(ctrl_desc[i].ctrl_type == CTRL_PASSIVE) + { + DBGL4(L4_MSG, "i4b_l4_daemon_detached", ("CMR_DCLOSE sent to unit %d\n", ctrl_desc[i].unit)); + + (*ctrl_desc[i].N_MGMT_COMMAND)(ctrl_desc[i].unit, CMR_DCLOSE, 0); + } + } + splx(x); +} + +#ifdef I4B_CD_DEBUG_PRINT + +extern char *print_l3state(call_desc_t *cd); + +void i4b_print_cdp(call_desc_t *cdp); +void i4b_print_cdx(int index); +void i4b_print_cda(void); +void i4b_print_cdaa(void); + +/*---------------------------------------------------------------------------* + * print a call descriptor by cd-pointer + *---------------------------------------------------------------------------*/ +void +i4b_print_cdp(call_desc_t *cdp) +{ + if((cdp > &(call_desc[N_CALL_DESC])) || (cdp < &(call_desc[0]))) + { + printf("i4b_print_cd: cdp out of range!\n"); + return; + } + + printf("i4b_print_cd: printing call descriptor %d at 0x%lx:\n", cdp - (&(call_desc[0])), (unsigned long)cdp); + + printf(" cdid = %d\n", cdp->cdid); + printf(" controller = %d (u=%d, dl=%d, b1=%d, b2=%d)\n", + cdp->controller, + ctrl_desc[cdp->controller].unit, + ctrl_desc[cdp->controller].dl_est, + ctrl_desc[cdp->controller].bch_state[CHAN_B1], + ctrl_desc[cdp->controller].bch_state[CHAN_B2]); + printf(" cr = 0x%02x\n", cdp->cr); + printf(" crflag = %d\n", cdp->crflag); + printf(" channelid = %d\n", cdp->channelid); + printf(" bprot = %d\n", cdp->bprot); + printf(" driver = %d\n", cdp->driver); + printf(" driver_unit = %d\n", cdp->driver_unit); + printf(" call_state = %d\n", cdp->call_state); + printf(" Q931state = %s\n", print_l3state(cdp)); + printf(" event = %d\n", cdp->event); + printf(" response = %d\n", cdp->response); + printf(" T303 = %d\n", cdp->T303); + printf("T303_first_to = %d\n", cdp->T303_first_to); + printf(" T305 = %d\n", cdp->T305); + printf(" T308 = %d\n", cdp->T308); + printf("T308_first_to = %d\n", cdp->T308_first_to); + printf(" T309 = %d\n", cdp->T309); + printf(" T310 = %d\n", cdp->T310); + printf(" T313 = %d\n", cdp->T313); + printf(" T400 = %d\n", cdp->T400); + printf(" dir = %s\n", cdp->dir == DIR_OUTGOING ? "out" : "in"); +} + +/*---------------------------------------------------------------------------* + * print a call descriptor by index + *---------------------------------------------------------------------------*/ +void +i4b_print_cdx(int index) +{ + if(index >= N_CALL_DESC) + { + printf("i4b_print_cdx: index %d >= N_CALL_DESC %d\n", index, N_CALL_DESC); + return; + } + i4b_print_cdp(&(call_desc[index])); +} + +/*---------------------------------------------------------------------------* + * print all call descriptors + *---------------------------------------------------------------------------*/ +void +i4b_print_cda(void) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + i4b_print_cdp(&(call_desc[i])); + } +} + +/*---------------------------------------------------------------------------* + * print all active call descriptors + *---------------------------------------------------------------------------*/ +void +i4b_print_cdaa(void) +{ + int i; + + for(i=0; i < N_CALL_DESC; i++) + { + if(call_desc[i].cdid != CDID_UNUSED) + { + i4b_print_cdp(&(call_desc[i])); + } + } +} + +#endif /* I4B_CD_DEBUG_PRINT */ + +#endif /* NI4BQ931 > 0 */ diff --git a/sys/i4b/layer4/i4b_l4timer.c b/sys/i4b/layer4/i4b_l4timer.c new file mode 100644 index 0000000..7a38e13 --- /dev/null +++ b/sys/i4b/layer4/i4b_l4timer.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_l4timer.c - timer and timeout handling for layer 4 + * -------------------------------------------------------- + * + * $Id: i4b_l4timer.c,v 1.10 1998/12/05 18:05:53 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:36:07 1998] + * + *---------------------------------------------------------------------------*/ + +#include "i4b.h" + +#if NI4B > 0 + +#include <sys/param.h> +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/mbuf.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#else +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_global.h> +#include <i4b/include/i4b_l3l4.h> +#include <i4b/include/i4b_mbuf.h> + +#include <i4b/layer4/i4b_l4.h> + +/*---------------------------------------------------------------------------* + * timer T400 timeout function + *---------------------------------------------------------------------------*/ +static void +T400_timeout(call_desc_t *cd) +{ + DBGL4(L4_ERR, "T400_timeout", ("cr = %d\n", cd->cr)); +} + +/*---------------------------------------------------------------------------* + * timer T400 start + *---------------------------------------------------------------------------*/ +void +T400_start(call_desc_t *cd) +{ + DBGL4(L4_MSG, "T400_start", ("cr = %d\n", cd->cr)); + + cd->T400 = TIMER_ACTIVE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + cd->T400_callout = timeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, T400DEF); +#else + timeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, T400DEF); +#endif +} + +/*---------------------------------------------------------------------------* + * timer T400 stop + *---------------------------------------------------------------------------*/ +void +T400_stop(call_desc_t *cd) +{ + DBGL4(L4_MSG, "T400_stop", ("cr = %d\n", cd->cr)); + + if(cd->T400 == TIMER_ACTIVE) + { + cd->T400 = TIMER_IDLE; +#if defined(__FreeBSD_version) && __FreeBSD_version >= 300001 + untimeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd, cd->T400_callout); +#else + untimeout((TIMEOUT_FUNC_T)T400_timeout, (void *)cd); +#endif + } +} + +#endif /* NI4B > 0 */ diff --git a/sys/i4b/tina-dd/README b/sys/i4b/tina-dd/README new file mode 100644 index 0000000..6a2386f --- /dev/null +++ b/sys/i4b/tina-dd/README @@ -0,0 +1,20 @@ + +THIS DRIVER IS NOT YET WORKING ! +================================ + +This adds support for the active ISDN card tina-dd manufactured by +Stollmann E+V GmbH in Hamburg, Germany. This card was also sold by +MIRO as the Miro P1. + +Christian Luehrs and Manfred Jung of Stollmann were very helpful +giving out docs and sources to support the development of a driver +for this card. + +The card supports many protocols. In order to make the card operable +you'll need the downloadable firmware which also can be found on the +www/ftp server, www.stollmann.de / ftp.stollmann.de. + +While developing this driver, i used fcdddss1.loc as of April 1994. + +The code is based in part on sources and header files written by +Stollmann for their driver development kit for the tina-dd. diff --git a/sys/i4b/tina-dd/i4b_tina_dd.c b/sys/i4b/tina-dd/i4b_tina_dd.c new file mode 100644 index 0000000..7a5e010 --- /dev/null +++ b/sys/i4b/tina-dd/i4b_tina_dd.c @@ -0,0 +1,330 @@ +/* + * Copyright (c) 1994, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tina_dd.c - i4b Stollman Tina-dd control device driver + * ---------------------------------------------------------- + * + * $Id: i4b_tina_dd.c,v 1.3 1998/12/05 18:06:19 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:41:38 1998] + * + *---------------------------------------------------------------------------*/ + +#include "tina.h" + +#if NTINA > 0 + +#include <sys/param.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <sys/ioccom.h> +#else +#include <sys/ioctl.h> +#endif +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/conf.h> +#include <sys/mbuf.h> +#include <sys/proc.h> +#include <sys/fcntl.h> +#include <sys/socket.h> +#include <net/if.h> + +#ifdef __FreeBSD__ +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> +#include <i386/isa/isa_device.h> +#else +#include <machine/bus.h> +#include <sys/device.h> +#include <i4b/i4b_debug.h> +#include <i4b/i4b_ioctl.h> +#endif + +#include <i4b/include/i4b_mbuf.h> +#include <i4b/tina-dd/i4b_tina_ioctl.h> + +static int openflag = 0; + +int tinaprobe(struct isa_device *dev); +int tinaattach(struct isa_device *dev); + +struct isa_driver tinadriver = { + tinaprobe, + tinaattach, + "tina", + 0 +}; + +static struct tina_softc { + int sc_unit; + int sc_iobase; +} tina_sc[NTINA]; + +static d_open_t tinaopen; +static d_close_t tinaclose; +static d_ioctl_t tinaioctl; +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +static d_poll_t tinapoll; +#endif + +#define CDEV_MAJOR 54 +static struct cdevsw tina_cdevsw = + { tinaopen, tinaclose, noread, nowrite, + tinaioctl, nostop, nullreset, nodevtotty, +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + tinapoll, nommap, NULL, "tina", NULL, -1 }; +#else + noselect, nommap, NULL, "tina", NULL, -1 }; +#endif + +static void setupaddr(unsigned short iobase, unsigned int addr); +static void readblock(unsigned short iobase, unsigned int addr, + unsigned char *dst, unsigned int len); +static void writeblock(unsigned short iobase, unsigned char *src, + unsigned long addr, int len); + +/*---------------------------------------------------------------------------* + * tina - device driver probe routine + *---------------------------------------------------------------------------*/ +int +tinaprobe(struct isa_device *dev) +{ + struct tina_softc *sc = &tina_sc[dev->id_unit]; + u_char byte; + +#define SETLOW 0x55 +#define SETMID 0xaa +#define SETHIGH 0x06 + + outb((dev->id_iobase + ADDR_CNTL), SETLOW); + + if((byte = inb(dev->id_iobase + ADDR_CNTL)) != SETLOW) + { + printf("tina%d: probe low failed, 0x%x != 0x%x\n", + dev->id_unit, byte, SETLOW); + return(0); + } + + outb((dev->id_iobase + ADDR_CNTM), SETMID); + if((byte = inb(dev->id_iobase + ADDR_CNTM)) != SETMID) + { + printf("tina%d: probe mid failed, 0x%x != 0x%x\n", + dev->id_unit, byte, SETMID); + return(0); + } + + outb((dev->id_iobase + ADDR_CNTH), SETHIGH); + if(((byte = inb(dev->id_iobase + ADDR_CNTH)) & 0x0f) != SETHIGH) + { + printf("tina%d: probe high failed, 0x%x != 0x%x\n", + dev->id_unit, byte, SETHIGH); + return(0); + } + + printf("tina%d: status register = 0x%x\n", + dev->id_unit, inb(dev->id_iobase + CTRL_STAT)); + + return(1); /* board found */ +} +#undef SETLOW +#undef SETMID +#undef SETHIGH + +/*---------------------------------------------------------------------------* + * tina - device driver attach routine + *---------------------------------------------------------------------------*/ +int +tinaattach(struct isa_device *dev) +{ + struct tina_softc *sc = &tina_sc[dev->id_unit]; + + sc->sc_unit = dev->id_unit; + sc->sc_iobase = dev->id_iobase; + + printf("tina%d: attaching Tina-dd\n", dev->id_unit); + + return(1); +} + +/*---------------------------------------------------------------------------* + * tina - device driver interrupt routine + *---------------------------------------------------------------------------*/ +void +tinaintr(int unit) +{ + struct tina_softc *sc = &tina_sc[unit]; +} + +#if BSD > 199306 && defined(__FreeBSD__) +/*---------------------------------------------------------------------------* + * initialization at kernel load time + *---------------------------------------------------------------------------*/ +static void +tinainit(void *unused) +{ + dev_t dev; + + dev = makedev(CDEV_MAJOR, 0); + + cdevsw_add(&dev, &tina_cdevsw, NULL); +} + +SYSINIT(tinadev, SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR, &tinainit, NULL); + +#endif /* BSD > 199306 && defined(__FreeBSD__) */ + +/*---------------------------------------------------------------------------* + * tinaopen - device driver open routine + *---------------------------------------------------------------------------*/ +static int +tinaopen(dev_t dev, int flag, int fmt, struct proc *p) +{ + if(minor(dev)) + return (ENXIO); + + if(openflag) + return (EBUSY); + + openflag = 1; + + return(0); +} + +/*---------------------------------------------------------------------------* + * tinaclose - device driver close routine + *---------------------------------------------------------------------------*/ +static int +tinaclose(dev_t dev, int flag, int fmt, struct proc *p) +{ + openflag = 0; + return(0); +} + +/*---------------------------------------------------------------------------* + * tinaioctl - device driver ioctl routine + *---------------------------------------------------------------------------*/ +static int +tinaioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) +{ + struct tina_softc *sc = &tina_sc[minor(dev)]; + u_short iobase = sc->sc_iobase; + int error = 0; + char *ptr; + int s; + + if(minor(dev)) + return(ENODEV); + + s = splimp(); + + switch(cmd) + { + /* hardware layer - control & status register */ + + case ISDN_GETCSR: /* return control register */ + *(unsigned char *)data = inb(iobase + CTRL_STAT); + break; + + case ISDN_SETCSR: /* set status register */ + outb((iobase + CTRL_STAT), *(unsigned char *)data); + break; + + /* hardware layer - dual ported memory */ + + case ISDN_GETBLK: /* get block from dual port mem */ + readblock(iobase, (*(struct record *)data).addr, + (*(struct record *)data).data, + (*(struct record *)data).length); + break; + + case ISDN_SETBLK: /* write block to dual port mem */ + writeblock(iobase, (*(struct record *)data).data, + (*(struct record *)data).addr, + (*(struct record *)data).length); + break; + + default: + error = ENOTTY; + break; + } + return(error); +} + +/*---------------------------------------------------------------------------* + * tinapoll - device driver poll routine + *---------------------------------------------------------------------------*/ +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +static int +tinapoll (dev_t dev, int events, struct proc *p) +{ + return (ENODEV); +} +#endif + +/*===========================================================================* + * tina dual ported memory access + *===========================================================================*/ + +/*---------------------------------------------------------------------------* + * setup address for accessing tina-dd ram + *---------------------------------------------------------------------------*/ +static void +setupaddr(unsigned short iobase, unsigned int addr) +{ + outb((iobase + ADDR_CNTL), (unsigned char) addr & 0xff); + outb((iobase + ADDR_CNTM), (unsigned char) ((addr >> 8) & 0xff)); + outb((iobase + ADDR_CNTH), (unsigned char) ((addr >> 16) & 0xff)); +} + + +/*---------------------------------------------------------------------------* + * read block from tina-dd dual ported ram + *---------------------------------------------------------------------------*/ +static void +readblock(unsigned short iobase, unsigned int addr, + unsigned char *dst, unsigned int len) +{ + setupaddr(iobase, addr); /* setup start address */ + + while(len--) /* tina-dd mem -> pc mem */ + *dst++ = inb(iobase + DATA_LOW_INC); +} + +/*---------------------------------------------------------------------------* + * write block to tina-dd dual ported ram + *---------------------------------------------------------------------------*/ +static void +writeblock(unsigned short iobase, unsigned char *src, + unsigned long addr, int len) +{ + setupaddr(iobase, addr); /* setup start address */ + + while(len--) /* pc mem -> tina-dd mem */ + outb((iobase + DATA_LOW_INC), *src++); +} + +#endif /* NTINA > 0 */ diff --git a/sys/i4b/tina-dd/i4b_tina_ioctl.h b/sys/i4b/tina-dd/i4b_tina_ioctl.h new file mode 100644 index 0000000..d51f16d --- /dev/null +++ b/sys/i4b/tina-dd/i4b_tina_ioctl.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 1994, 1998 Hellmuth Michaelis. All rights reserved. + * + * Based on code written by Stollmann GmbH, Hamburg. Many thanks to + * Christian Luehrs and Manfred Jung for docs, sources and answers! + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b_tina_ioctl.h - i4b Stollman Tina-dd ioctl header file + * --------------------------------------------------------- + * + * $Id: i4b_tina_ioctl.h,v 1.2 1998/12/05 18:06:20 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:41:51 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _I4B_TINA_IOCTL_H_ +#define _I4B_TINA_IOCTL_H_ + +#define TINA_IOSIZE 8 /* 8 byte wide iospace occupied */ + +/*---------------------------------------------------------------------------* + * register offsets in i/o address space + *---------------------------------------------------------------------------*/ + +#define CTRL_STAT 0 /* control & status */ + +#define ADDR_CNTL 1 /* address pointer low */ +#define ADDR_CNTM 2 /* address pointer mid */ +#define ADDR_CNTH 3 /* address pointer high */ + +#define DATA_LOW 4 /* data register low */ +#define DATA_HIGH 5 /* data register high */ + +#define DATA_LOW_INC 6 /* data register low, post inc */ +#define DATA_HIGH_INC 7 /* data register high, post inc */ + +/*---------------------------------------------------------------------------* + * status register (CTRL_STAT read access) + *---------------------------------------------------------------------------*/ + +#define CR_INTC 0x80 /* irq FROM tina-dd TO pc active */ +#define CR_INTP 0x40 /* irq FROM pc TO tina-dd active */ +#define CR_INTPA 0x20 /* irq FROM pc TO tina-dd active */ +#define CR_NMI 0x10 /* nmi FROM PC TO tina-dd active */ +#define CR_FLASHLD 0x08 /* read of the FLASHLD-bit (n/c) */ +#define CR_S2C 0x04 /* info bit */ +#define CR_S1C 0x02 /* info bit */ +#define CR_S0C 0x01 /* info bit */ + +/*---------------------------------------------------------------------------* + * control register (CTRL_STAT write access) + *---------------------------------------------------------------------------*/ + +#define CR_CLR_INTC 0x80 /* clear irq on tina-dd */ +#define CR_SET_INTP 0x40 /* trigger irq on tina-dd */ +#define CR_RESET 0x20 /* reset tina-dd */ +#define CR_SET_NMI 0x10 /* trigger nmi on tina-dd */ +#define CR_SET_FLASHLD 0x08 /* activates pin FLASHLD (n/c) */ +#define CR_S2P 0x04 /* info bit (not readable !) */ +#define CR_S1P 0x02 /* info bit (not readable !) */ +#define CR_S0P 0x01 /* info bit (not readable !) */ + +/*---------------------------------------------------------------------------* + * misc definitions in dual-ported mem on board of tina-dd + *---------------------------------------------------------------------------*/ + +#define FW_SYSCB 0x200 /* address of FW SYSCB / MJ 300392 */ +#define FW_SINFO_NAME 0x220 /* address of general info label */ + +#define FW_HW_TYPE 0x224 /* address of hardware type byte: */ +#define FW_HW_UNDEF 0x00 /* undefined .. */ +#define FW_HW_TINA_DD 0x10 /* TINA-dd */ +#define FW_HW_TINA_DS 0x20 /* TINA-ds (B channel/ser ?) */ +#define FW_HW_TINA_D 0x30 /* TINA-d (one B channel ?) */ +#define FW_HW_TINA_DDM 0x40 /* TINA-dd with fax module */ +#define FW_HW_TINA_DDS 0x50 /* TINA-dd with fax/voice module */ +#define FW_HW_SICCE 0x80 /* X.25 board */ +#define FW_HW_ASIC 0x01 /* ASIC version bit */ + +#define FW_STAT 0x228 /* address of firmware status byte */ +#define FW_READY 0x20 /* firmware ready bit */ +#define FW_BOOTPRM_RDY 0x02 /* boot PROM ready */ +#define FW_UNDEF_0 0x00 /* undefined */ +#define FW_UNDEF_1 0xFF /* undefined */ + +#define FW_SINFO_ID "SYSI" /* general info label for FW > 2.13*/ +#define FW_SINFO_ID_LEN 4 + +#define FW_ADDR_PROFPTR 0x260 /* addr of ptr to board profile */ + +/*===========================================================================* + * Layer 0 - Hardware layer + *===========================================================================*/ + +/* control and status register access */ + +#define ISDN_GETCSR _IOR('I', 1, unsigned char) /* get csr */ +#define ISDN_SETCSR _IOW('I', 2, unsigned char) /* set csr */ + +/* dual ported ram access */ + +#define ISDN_GETBLK _IOWR('I', 3, struct record) /* get dpr record */ +#define ISDN_SETBLK _IOW('I', 4, struct record) /* set dpr record */ + +/*---------------------------------------------------------------------------* + * record structure for dual ported ram block rd/wr + *---------------------------------------------------------------------------*/ +struct record { + unsigned int length; /* length of data block */ + unsigned int addr; /* address of mem on tina-dd board */ + unsigned char *data; /* pointer to the datablock itself */ +}; + +#endif /* _I4B_TINA_IOCTL_H_ */ diff --git a/usr.sbin/Makefile b/usr.sbin/Makefile index 60a7a5f..ce29976 100644 --- a/usr.sbin/Makefile +++ b/usr.sbin/Makefile @@ -1,5 +1,5 @@ # From: @(#)Makefile 5.20 (Berkeley) 6/12/93 -# $Id: Makefile,v 1.139 1998/12/27 16:43:15 phk Exp $ +# $Id: Makefile,v 1.140 1998/12/27 21:30:39 phk Exp $ # XXX MISSING: mkproto SUBDIR= IPXrouted \ @@ -22,6 +22,7 @@ SUBDIR= IPXrouted \ dev_mkdb \ diskpart \ edquota \ + i4b \ inetd \ iostat \ ipfstat \ diff --git a/usr.sbin/i4b/Makefile b/usr.sbin/i4b/Makefile new file mode 100644 index 0000000..3c12d78 --- /dev/null +++ b/usr.sbin/i4b/Makefile @@ -0,0 +1,4 @@ +SUBDIR = isdntrace isdndebug isdnd alawulaw man isdntest \ + isdntel isdntelctl isdnmonitor isdndecode + +.include <bsd.subdir.mk> diff --git a/usr.sbin/i4b/Makefile.inc b/usr.sbin/i4b/Makefile.inc new file mode 100644 index 0000000..691d738 --- /dev/null +++ b/usr.sbin/i4b/Makefile.inc @@ -0,0 +1,14 @@ +# if you don't like curses stuff in the daemon (i.e. don't intend +# to ever run it in the foreground but are using the monitoring +# utilities instead) define this to compile it without. +#I4B_WITHOUT_CURSES = 1 + +# if you would like monitoring support, define this +I4B_EXTERNAL_MONITOR = 1 + +# for the security conscious type: restrict monitoring to the +# local machine by not compiling any tcp/ip support for monitoring +# at all +#I4B_NOTCPIP_MONITOR = 1 + +.include "${.CURDIR}/../../Makefile.inc" diff --git a/usr.sbin/i4b/alawulaw/Makefile b/usr.sbin/i4b/alawulaw/Makefile new file mode 100644 index 0000000..1daa481 --- /dev/null +++ b/usr.sbin/i4b/alawulaw/Makefile @@ -0,0 +1,7 @@ +PROG = alaw2ulaw +SRC = alaw2ulaw.c +CFLAGS += -Wall -g -DDEBUG +LINKS = ${BINDIR}/alaw2ulaw ${BINDIR}/ulaw2alaw +MAN1 = alaw2ulaw.1 ulaw2alaw.1 + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/alawulaw/alaw2ulaw.1 b/usr.sbin/i4b/alawulaw/alaw2ulaw.1 new file mode 100644 index 0000000..fea7fa5 --- /dev/null +++ b/usr.sbin/i4b/alawulaw/alaw2ulaw.1 @@ -0,0 +1,70 @@ +.\" +.\" Copyright (c) 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: alaw2ulaw.1,v 1.3 1998/12/05 18:02:35 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 17:57:34 1998] +.\" +.\" -hm writing manual pages +.\" +.\" +.Dd January 23, 1998 +.Dt alaw2ulaw 1 +.Sh NAME +.Nm alaw2ulaw +.Nd convert sound data +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm alaw2ulaw +is part of the isdn4bsd package and is used convert sound data between +uLaw coded data to ALaw coded data and vice versa. +.Pp +It reads data from stdin and outputs converted data to stdout. +.Pp +In case it is run as +.Em alaw2ulaw +it converts ALaw input data to uLaw output. +.Pp +In case it is run as +.Em ulaw2alaw +it converts uLaw input data to ALaw output. +.Pp + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +alaw2ulaw <file.alaw >file.ulaw +.Ed +.Pp +converts ALaw input data file file.alaw to uLaw output file file.ulaw. + +.Sh STANDARDS +ITU Recommendations G.711 + +.Sh AUTHOR +The +.Nm +utility and this man page were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/alawulaw/alaw2ulaw.c b/usr.sbin/i4b/alawulaw/alaw2ulaw.c new file mode 100644 index 0000000..d13e41d --- /dev/null +++ b/usr.sbin/i4b/alawulaw/alaw2ulaw.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 1997 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * convert a-law / u-law sound files + * --------------------------------- + * + * last edit-date: [Sat Dec 5 17:57:56 1998] + * + * $Id: alaw2ulaw.c,v 1.2 1998/12/05 18:02:36 hm Exp $ + * + * -hm telephony is ready + * + *---------------------------------------------------------------------------*/ + +#include <string.h> +#include <unistd.h> + +#define BUF_SIZ 2048 + +unsigned char alaw_ulaw[]; +unsigned char ulaw_alaw[]; + +int main(int argc, char *argv[]) +{ + int i, j; + unsigned char buffer[BUF_SIZ]; + char *p; + unsigned char *cp; + + if((p = rindex(*argv, '/')) != NULL) + p++; + else + p = *argv; + + if(!strcmp(p, "ulaw2alaw")) + { + cp = ulaw_alaw; + } + else if(!strcmp(p, "alaw2ulaw")) + { + cp = alaw_ulaw; + } + else + { + return(1); + } + + while(((j = read(0, buffer, BUF_SIZ)) > 0)) + { + for(i = 0; i < j; i++) + buffer[i] = cp[buffer[i]]; + write(1, buffer, j); + } + return(0); +} + +unsigned char alaw_ulaw[] = { + 0x002a, 0x00a9, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0048, 0x00c8, + 0x0039, 0x00b9, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d7, + 0x0022, 0x00a1, 0x005b, 0x00dd, 0x001f, 0x009f, 0x0040, 0x00c0, + 0x0031, 0x00b1, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00cf, + 0x002e, 0x00ad, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004c, 0x00cc, + 0x003d, 0x00bd, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00db, + 0x0026, 0x00a5, 0x005d, 0x00df, 0x001f, 0x009f, 0x0044, 0x00c4, + 0x0035, 0x00b5, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d3, + 0x0028, 0x00a7, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0046, 0x00c6, + 0x0037, 0x00b7, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0053, 0x00d5, + 0x0020, 0x009f, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf, + 0x002f, 0x00af, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004d, 0x00ce, + 0x002c, 0x00ab, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004a, 0x00ca, + 0x003b, 0x00bb, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0057, 0x00d9, + 0x0024, 0x00a3, 0x005d, 0x00df, 0x001f, 0x009f, 0x0042, 0x00c2, + 0x0033, 0x00b3, 0x006b, 0x00ef, 0x001f, 0x009f, 0x004f, 0x00d1, + 0x002b, 0x00aa, 0x0063, 0x00e3, 0x001f, 0x009f, 0x0049, 0x00c9, + 0x003a, 0x00ba, 0x0077, 0x00f7, 0x001f, 0x009f, 0x0057, 0x00d7, + 0x0023, 0x00a2, 0x005d, 0x00dd, 0x001f, 0x009f, 0x0041, 0x00c1, + 0x0032, 0x00b2, 0x006b, 0x00eb, 0x001f, 0x009f, 0x004f, 0x00cf, + 0x002f, 0x00ae, 0x0067, 0x00e7, 0x001f, 0x009f, 0x004d, 0x00cd, + 0x003e, 0x00be, 0x00ff, 0x00ff, 0x001f, 0x009f, 0x005b, 0x00db, + 0x0027, 0x00a6, 0x005f, 0x00df, 0x001f, 0x009f, 0x0045, 0x00c5, + 0x0036, 0x00b6, 0x006f, 0x00ef, 0x001f, 0x009f, 0x0053, 0x00d3, + 0x0029, 0x00a8, 0x005f, 0x00e3, 0x001f, 0x009f, 0x0047, 0x00c7, + 0x0038, 0x00b8, 0x006f, 0x00f7, 0x001f, 0x009f, 0x0055, 0x00d5, + 0x0021, 0x00a0, 0x005b, 0x00dd, 0x001f, 0x009f, 0x003f, 0x00bf, + 0x0030, 0x00b0, 0x0067, 0x00eb, 0x001f, 0x009f, 0x004e, 0x00ce, + 0x002d, 0x00ac, 0x0063, 0x00e7, 0x001f, 0x009f, 0x004b, 0x00cb, + 0x003c, 0x00bc, 0x0077, 0x00ff, 0x001f, 0x009f, 0x0059, 0x00d9, + 0x0025, 0x00a4, 0x005d, 0x00df, 0x001f, 0x009f, 0x0043, 0x00c3, + 0x0034, 0x00b4, 0x006b, 0x00ef, 0x001f, 0x009f, 0x0051, 0x00d1 +}; + +unsigned char ulaw_alaw[] = { + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, + 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00fc, 0x00ac, + 0x0050, 0x00d0, 0x0010, 0x0090, 0x0070, 0x00f0, 0x0030, 0x00b0, + 0x0040, 0x00c0, 0x0000, 0x0080, 0x0060, 0x00e0, 0x0020, 0x00a0, + 0x00d8, 0x0018, 0x0098, 0x0078, 0x00f8, 0x0038, 0x00b8, 0x0048, + 0x00c8, 0x0008, 0x0088, 0x0068, 0x00e8, 0x0028, 0x00a8, 0x00d6, + 0x0096, 0x0076, 0x00f6, 0x0036, 0x00b6, 0x0046, 0x00c6, 0x0006, + 0x0086, 0x0066, 0x00e6, 0x0026, 0x00a6, 0x00de, 0x009e, 0x00fe, + 0x00fe, 0x00be, 0x00be, 0x00ce, 0x00ce, 0x008e, 0x008e, 0x00ee, + 0x00ee, 0x00d2, 0x00d2, 0x00f2, 0x00f2, 0x00c2, 0x00c2, 0x00e2, + 0x00e2, 0x00e2, 0x00da, 0x00da, 0x00da, 0x00da, 0x00fa, 0x00fa, + 0x00fa, 0x00fa, 0x00ca, 0x00ca, 0x00ca, 0x00ca, 0x00ea, 0x00ea, + 0x00ea, 0x00ea, 0x00ea, 0x00ea, 0x00eb, 0x00eb, 0x00eb, 0x00eb, + 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, 0x00eb, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, 0x00fd, + 0x00d1, 0x0011, 0x0091, 0x0071, 0x00f1, 0x0031, 0x00b1, 0x0041, + 0x00c1, 0x0001, 0x0081, 0x0061, 0x00e1, 0x0021, 0x00a1, 0x0059, + 0x00d9, 0x0019, 0x0099, 0x0079, 0x00f9, 0x0039, 0x00b9, 0x0049, + 0x00c9, 0x0009, 0x0089, 0x0069, 0x00e9, 0x0029, 0x00a9, 0x0057, + 0x0017, 0x0097, 0x0077, 0x00f7, 0x0037, 0x00b7, 0x0047, 0x00c7, + 0x0007, 0x0087, 0x0067, 0x00e7, 0x0027, 0x00a7, 0x00df, 0x009f, + 0x009f, 0x00ff, 0x00ff, 0x00bf, 0x00bf, 0x00cf, 0x00cf, 0x008f, + 0x008f, 0x00ef, 0x00ef, 0x00af, 0x00af, 0x00d3, 0x00d3, 0x00f3, + 0x00f3, 0x00f3, 0x00c3, 0x00c3, 0x00c3, 0x00c3, 0x00e3, 0x00e3, + 0x00e3, 0x00e3, 0x00db, 0x00db, 0x00db, 0x00db, 0x00fb, 0x00fb, + 0x00fb, 0x00fb, 0x00fb, 0x00fb, 0x00cb, 0x00cb, 0x00cb, 0x00cb, + 0x00cb, 0x00cb, 0x00cb, 0x00cb, 0x00eb, 0x00eb, 0x00eb, 0x00eb +}; + +/* EOF */ diff --git a/usr.sbin/i4b/alawulaw/ulaw2alaw.1 b/usr.sbin/i4b/alawulaw/ulaw2alaw.1 new file mode 100644 index 0000000..4c43c15 --- /dev/null +++ b/usr.sbin/i4b/alawulaw/ulaw2alaw.1 @@ -0,0 +1,70 @@ +.\" +.\" Copyright (c) 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: ulaw2alaw.1,v 1.3 1998/12/05 18:02:37 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 17:58:07 1998] +.\" +.\" -hm writing manual pages +.\" +.\" +.Dd January 23, 1998 +.Dt ulaw2alaw 1 +.Sh NAME +.Nm ulaw2alaw +.Nd convert sound data +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +.Nm ulaw2alaw +is part of the isdn4bsd package and is used convert sound data between +uLaw coded data to ALaw coded data and vice versa. +.Pp +It reads data from stdin and outputs converted data to stdout. +.Pp +In case it is run as +.Em alaw2ulaw +it converts ALaw input data to uLaw output. +.Pp +In case it is run as +.Em ulaw2alaw +it converts uLaw input data to ALaw output. +.Pp + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +ulaw2alaw <file.ulaw >file.alaw +.Ed +.Pp +converts uLaw input data file file.ulaw to ALaw output file file.alaw. + +.Sh STANDARDS +ITU Recommendations G.711 + +.Sh AUTHOR +The +.Nm +utility and this man page were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/isdnd/Makefile b/usr.sbin/i4b/isdnd/Makefile new file mode 100644 index 0000000..2bda2bb --- /dev/null +++ b/usr.sbin/i4b/isdnd/Makefile @@ -0,0 +1,32 @@ + +PROG = isdnd + +SRCS = rc_parse.y rc_scan.l main.c rc_config.c log.c curses.c \ + process.c rates.c msghdl.c fsm.c support.c timer.c \ + exec.c dial.c monitor.c pcause.c controller.c alias.c \ + y.tab.h + +COPTS += -I${.CURDIR}/../isdnmonitor -I${.CURDIR}/../isdntel -I${.OBJDIR} + +# compile debug support +COPTS += -DDEBUG + +# enable rtprio usage +COPTS += -DUSE_RTPRIO + +MAN8 = isdnd.8 +MAN5 = isdnd.rc.5 isdnd.rates.5 isdnd.acct.5 + +.include <bsd.prog.mk> + +.if !defined(I4B_WITHOUT_CURSES) +COPTS += -DUSE_CURSES +LDADD += -lcurses +.endif + +.if defined(I4B_EXTERNAL_MONITOR) +COPTS += -DI4B_EXTERNAL_MONITOR +.if defined(I4B_NOTCPIP_MONITOR) +COPTS += -DI4B_NOTCPIP_MONITOR +.endif +.endif diff --git a/usr.sbin/i4b/isdnd/alias.c b/usr.sbin/i4b/isdnd/alias.c new file mode 100644 index 0000000..b802776 --- /dev/null +++ b/usr.sbin/i4b/isdnd/alias.c @@ -0,0 +1,191 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdnd - common aliasfile handling + * ================================= + * + * NOTE: this has to stay in sync with isdntel/alias.c to be able + * to share a common aliasfile! + * + * $Id: alias.c,v 1.5 1998/12/05 18:03:03 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:05:40 1998] + * + *----------------------------------------------------------------------------*/ + +#include "isdnd.h" + +static struct alias *firsta = NULL; + +#define MAXBUFSZ 256 + +static void free_alias(struct alias *ptr); + +/*---------------------------------------------------------------------------* + * read in and init aliases + *---------------------------------------------------------------------------*/ +void +init_alias(char *filename) +{ + FILE *fp; + char buffer[MAXBUFSZ + 1]; + char number[MAXBUFSZ + 1]; + char name[MAXBUFSZ + 1]; + char *s, *d; + struct alias *newa = NULL; + struct alias *lasta = NULL; + + firsta = NULL; + + if((fp = fopen(filename, "r")) == NULL) + { + log(LL_ERR, "init_alias: error opening aliasfile %s: %s!", filename, strerror(errno)); + exit(1); + } + + while((fgets(buffer, MAXBUFSZ, fp)) != NULL) + { + if(buffer[0] == '#' || buffer[0] == ' ' || + buffer[0] == '\t' || buffer[0] == '\n') + { + continue; + } + + s = buffer; + d = number; + + while(*s && (isdigit(*s))) + *d++ = *s++; + + *d = '\0'; + + while(*s && (isspace(*s))) + s++; + + d = name; + + while(*s && (isprint(*s))) + *d++ = *s++; + + *d = '\0'; + + if((strlen(number) > 1) && (strlen(name) > 1)) + { + if((newa = (struct alias *) malloc(sizeof(struct alias))) == NULL) + { + log(LL_ERR, "init_alias: malloc failed for struct alias!\n"); + exit(1); + } + + if((newa->number = (char *) malloc(strlen(number)+1)) == NULL) + { + log(LL_ERR, "init_alias: malloc failed for number alias!\n"); + exit(1); + } + + if((newa->name = (char *) malloc(strlen(name)+1)) == NULL) + { + log(LL_ERR, "init_alias: malloc failed for name alias!\n"); + exit(1); + } + + strcpy(newa->name, name); + strcpy(newa->number, number); + newa->next = NULL; + + if(firsta == NULL) + { + firsta = newa; + } + else + { + lasta->next = newa; + } + lasta = newa; + } + } + fclose(fp); +} + +/*---------------------------------------------------------------------------* + * free all aliases + *---------------------------------------------------------------------------*/ +void +free_aliases(void) +{ + free_alias(firsta); +} + +/*---------------------------------------------------------------------------* + * free aliases + *---------------------------------------------------------------------------*/ +static void +free_alias(struct alias *ptr) +{ + + if(ptr == NULL) + return; + + if(ptr->next != NULL) + free_alias(ptr->next); + + if(ptr->number != NULL) + free(ptr->number); + + if(ptr->name != NULL) + free(ptr->name); + + free(ptr); +} + +/*---------------------------------------------------------------------------* + * try to find alias for number. if no alias found, return number. + *---------------------------------------------------------------------------*/ +char * +get_alias(char *number) +{ + struct alias *ca = NULL; + + if(firsta == NULL) + return(number); + + ca = firsta; + + for(;;) + { + if(strlen(number) == strlen(ca->number)) + { + if(!(strcmp(number, ca->number))) + return(ca->name); + } + if(ca->next == NULL) + break; + ca = ca->next; + } + return(number); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/config.h b/usr.sbin/i4b/isdnd/config.h new file mode 100644 index 0000000..22c947a --- /dev/null +++ b/usr.sbin/i4b/isdnd/config.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - compile time configuration header file + * --------------------------------------------------- + * + * $Id: config.h,v 1.6 1998/12/05 18:03:05 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:05:56 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _CONFIG_H_ +#define _CONFIG_H_ + +/* general values */ + +#define UMASK 022 /* file creation perm mask */ +#define CFG_ENTRY_MAX 32 /* max no of config entries */ +#define ISDN_CTRL_MAX 4 /* max no of controllers */ +#define MAX_RE 8 /* max regular expression entries */ + +/* monitor max values */ + +#define MAX_MHOSTS 8 /* max allowed monitor hosts */ + +/* timouts */ + +#define TIMEOUT_CONNECT_ACTIVE 30 /* seconds to wait for MSG_CONN_ACT */ + +/* utility programs forked */ + +#define REGPROG_DEF "program" /* default program to use for regexpr */ +#define ANSWERPROG_DEF "answer" /* default telephone answer program */ + +#endif /* _CONFIG_H_ */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/controller.c b/usr.sbin/i4b/isdnd/controller.c new file mode 100644 index 0000000..b3cfcf9 --- /dev/null +++ b/usr.sbin/i4b/isdnd/controller.c @@ -0,0 +1,329 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - controller state support routines + * ---------------------------------------------- + * + * $Id: controller.c,v 1.10 1998/12/05 18:03:06 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:06:10 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +/*--------------------------------------------------------------------------* + * init controller state table entry + *--------------------------------------------------------------------------*/ +int +init_controller_state(int controller, int ctrl_type, int card_type, int tei) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "init_controller_state: invalid controller number [%d]!", controller); + return(ERROR); + } + + /* init controller tab */ + + if(ctrl_type == CTRL_PASSIVE) + { + if((card_type > CARD_TYPEP_UNK) && + (card_type <= CARD_TYPEP_MAX)) + { + isdn_ctrl_tab[controller].ctrl_type = ctrl_type; + isdn_ctrl_tab[controller].card_type = card_type; + isdn_ctrl_tab[controller].state = CTRL_UP; + isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE; + isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE; + isdn_ctrl_tab[controller].freechans = MAX_CHANCTRL; + isdn_ctrl_tab[controller].tei = tei; + log(LL_DMN, "init_controller_state: controller %d is %s", + controller, + name_of_controller(isdn_ctrl_tab[controller].ctrl_type, + isdn_ctrl_tab[controller].card_type)); + } + else + { + log(LL_ERR, "init_controller_state: unknown card type %d", card_type); + return(ERROR); + } + + } + else if(ctrl_type == CTRL_DAIC) + { + isdn_ctrl_tab[controller].ctrl_type = ctrl_type; + isdn_ctrl_tab[controller].card_type = card_type; + isdn_ctrl_tab[controller].state = CTRL_DOWN; + isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE; + isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE; + isdn_ctrl_tab[controller].freechans = MAX_CHANCTRL; + isdn_ctrl_tab[controller].tei = -1; + log(LL_DMN, "init_controller_state: controller %d is %s", + controller, + name_of_controller(isdn_ctrl_tab[controller].ctrl_type, + isdn_ctrl_tab[controller].card_type)); + } + else + { + /* XXX active controller init here !!! */ + + log(LL_ERR, "init_controller_state: unknown controller type %d", ctrl_type); + return(ERROR); + } + return(GOOD); +} + +/*--------------------------------------------------------------------------* + * set controller state to UP/DOWN + *--------------------------------------------------------------------------*/ +int +set_controller_state(int controller, int state) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "set_controller_state: invalid controller number [%d]!", controller); + return(ERROR); + } + + if(state == CTRL_UP) + { + isdn_ctrl_tab[controller].state = CTRL_UP; + DBGL(DL_CNST, (log(LL_DBG, "set_controller_state: controller [%d] set UP!", controller))); + } + else if (state == CTRL_DOWN) + { + isdn_ctrl_tab[controller].state = CTRL_DOWN; + DBGL(DL_CNST, (log(LL_DBG, "set_controller_state: controller [%d] set DOWN!", controller))); + } + else + { + log(LL_ERR, "set_controller_state: invalid controller state [%d]!", state); + return(ERROR); + } + return(GOOD); +} + +/*--------------------------------------------------------------------------* + * get controller state + *--------------------------------------------------------------------------*/ +int +get_controller_state(int controller) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "set_controller_state: invalid controller number [%d]!", controller); + return(ERROR); + } + return(isdn_ctrl_tab[controller].state); +} + +/*--------------------------------------------------------------------------* + * decrement number of free channels for controller + *--------------------------------------------------------------------------*/ +int +decr_free_channels(int controller) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "decr_free_channels: invalid controller number [%d]!", controller); + return(ERROR); + } + if(isdn_ctrl_tab[controller].freechans > 0) + { + (isdn_ctrl_tab[controller].freechans)--; + DBGL(DL_CNST, (log(LL_DBG, "decr_free_channels: ctrl %d, now %d chan free", controller, isdn_ctrl_tab[controller].freechans))); + return(GOOD); + } + else + { + log(LL_ERR, "decr_free_channels: controller [%d] already 0 free chans!", controller); + return(ERROR); + } +} + +/*--------------------------------------------------------------------------* + * increment number of free channels for controller + *--------------------------------------------------------------------------*/ +int +incr_free_channels(int controller) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "incr_free_channels: invalid controller number [%d]!", controller); + return(ERROR); + } + if(isdn_ctrl_tab[controller].freechans < MAX_CHANCTRL) + { + (isdn_ctrl_tab[controller].freechans)++; + DBGL(DL_CNST, (log(LL_DBG, "incr_free_channels: ctrl %d, now %d chan free", controller, isdn_ctrl_tab[controller].freechans))); + return(GOOD); + } + else + { + log(LL_ERR, "incr_free_channels: controller [%d] already 2 free chans!", controller); + return(ERROR); + } +} + +/*--------------------------------------------------------------------------* + * get number of free channels for controller + *--------------------------------------------------------------------------*/ +int +get_free_channels(int controller) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "get_free_channels: invalid controller number [%d]!", controller); + return(ERROR); + } + DBGL(DL_CNST, (log(LL_DBG, "get_free_channels: ctrl %d, %d chan free", controller, isdn_ctrl_tab[controller].freechans))); + return(isdn_ctrl_tab[controller].freechans); +} + +/*--------------------------------------------------------------------------* + * set channel state to busy + *--------------------------------------------------------------------------*/ +int +set_channel_busy(int controller, int channel) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "set_channel_busy: invalid controller number [%d]!", controller); + return(ERROR); + } + + switch(channel) + { + case CHAN_B1: + if(isdn_ctrl_tab[controller].stateb1 == CHAN_RUN) + { + DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B1 already busy!", controller))); + } + else + { + isdn_ctrl_tab[controller].stateb1 = CHAN_RUN; + DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B1 set to BUSY!", controller))); + } + break; + + case CHAN_B2: + if(isdn_ctrl_tab[controller].stateb2 == CHAN_RUN) + { + DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B2 already busy!", controller))); + } + else + { + isdn_ctrl_tab[controller].stateb2 = CHAN_RUN; + DBGL(DL_CNST, (log(LL_DBG, "set_channel_busy: controller [%d] channel B2 set to BUSY!", controller))); + } + break; + + default: + log(LL_ERR, "set_channel_busy: controller [%d], invalid channel [%d]!", controller, channel); + return(ERROR); + break; + } + return(GOOD); +} + +/*--------------------------------------------------------------------------* + * set channel state to idle + *--------------------------------------------------------------------------*/ +int +set_channel_idle(int controller, int channel) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "set_channel_idle: invalid controller number [%d]!", controller); + return(ERROR); + } + + switch(channel) + { + case CHAN_B1: + if(isdn_ctrl_tab[controller].stateb1 == CHAN_IDLE) + { + DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B1 already idle!", controller))); + } + else + { + isdn_ctrl_tab[controller].stateb1 = CHAN_IDLE; + DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B1 set to IDLE!", controller))); + } + break; + + case CHAN_B2: + if(isdn_ctrl_tab[controller].stateb2 == CHAN_IDLE) + { + DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B2 already idle!", controller))); + } + else + { + isdn_ctrl_tab[controller].stateb2 = CHAN_IDLE; + DBGL(DL_CNST, (log(LL_DBG, "set_channel_idle: controller [%d] channel B2 set to IDLE!", controller))); + } + break; + + default: + log(LL_ERR, "set_channel_idle: controller [%d], invalid channel [%d]!", controller, channel); + return(ERROR); + break; + } + return(GOOD); +} + +/*--------------------------------------------------------------------------* + * return channel state + *--------------------------------------------------------------------------*/ +int +ret_channel_state(int controller, int channel) +{ + if((controller < 0) || (controller >= ncontroller)) + { + log(LL_ERR, "ret_channel_state: invalid controller number [%d]!", controller); + return(ERROR); + } + + switch(channel) + { + case CHAN_B1: + return(isdn_ctrl_tab[controller].stateb1); + break; + + case CHAN_B2: + return(isdn_ctrl_tab[controller].stateb2); + break; + + default: + log(LL_ERR, "ret_channel_state: controller [%d], invalid channel [%d]!", controller, channel); + return(ERROR); + break; + } + return(ERROR); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/curses.c b/usr.sbin/i4b/isdnd/curses.c new file mode 100644 index 0000000..b505382 --- /dev/null +++ b/usr.sbin/i4b/isdnd/curses.c @@ -0,0 +1,633 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - curses fullscreen output + * ------------------------------------- + * + * $Id: curses.c,v 1.27 1998/12/05 18:03:08 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:06:24 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef USE_CURSES + +#include "isdnd.h" + +#define CHPOS(cfgp) (((cfgp)->isdncontrollerused*2) + (cfgp)->isdnchannelused) + +/*---------------------------------------------------------------------------* + * init curses fullscreen display + *---------------------------------------------------------------------------*/ +void +init_screen(void) +{ + char buffer[512]; + int uheight, lheight; + int i, j; + cfg_entry_t *p; + + initscr(); /* curses init */ + + if((COLS < 80) || (LINES < 24)) + { + log(LL_ERR, "ERROR, minimal screensize must be 80x24, is %dx%d, terminating!",COLS, LINES); + do_exit(1); + } + + noecho(); + raw(); + + uheight = ncontroller * 2; /* cards * b-channels */ + lheight = LINES - uheight - 6 + 1; /* rest of display */ + + if((upper_w = newwin(uheight, COLS, UPPER_B, 0)) == NULL) + { + log(LL_ERR, "ERROR, curses init upper window, terminating!"); + exit(1); + } + + if((mid_w = newwin(1, COLS, UPPER_B+uheight+1, 0)) == NULL) + { + log(LL_ERR, "ERROR, curses init mid window, terminating!"); + exit(1); + } + + if((lower_w = newwin(lheight, COLS, UPPER_B+uheight+3, 0)) == NULL) + { + log(LL_ERR, "ERROR, curses init lower window, LINES = %d, lheight = %d, uheight = %d, terminating!", LINES, lheight, uheight); + exit(1); + } + + scrollok(lower_w, 1); + + sprintf(buffer, "----- isdn controller channel state ------------- isdnd %02d.%02d.%d [pid %d] -", VERSION, REL, STEP, (int)getpid()); + + while(strlen(buffer) < COLS) + strcat(buffer, "-"); + + move(0, 0); + standout(); + addstr(buffer); + standend(); + + move(1, 0); + /* 01234567890123456789012345678901234567890123456789012345678901234567890123456789 */ + addstr("c tei b remote iface dir outbytes obps inbytes ibps units"); + + sprintf(buffer, "----- isdn userland interface state ------------------------------------------"); + while(strlen(buffer) < COLS) + strcat(buffer, "-"); + + move(uheight+2, 0); + standout(); + addstr(buffer); + standend(); + + sprintf(buffer, "----- isdnd logfile display --------------------------------------------------"); + while(strlen(buffer) < COLS) + strcat(buffer, "-"); + + move(uheight+4, 0); + standout(); + addstr(buffer); + standend(); + + move(uheight+5, 0); + addstr("Date Time Typ Information Description"); + + refresh(); + + for(i=0, j=0; i <= ncontroller; i++, j+=2) + { + if(isdn_ctrl_tab[i].tei == -1) + mvwprintw(upper_w, j, H_CNTL, "%d --- 1 ", i); + else + mvwprintw(upper_w, j, H_CNTL, "%d %3d 1 ", i, isdn_ctrl_tab[i].tei); + mvwprintw(upper_w, j+1, H_CNTL, " L12 2 "); + } + wrefresh(upper_w); + + for(i=0, j=0; i < nentries; i++) /* walk thru all entries */ + { + p = &cfg_entry_tab[i]; /* get ptr to enry */ + + mvwprintw(mid_w, 0, j, "%s%d ", bdrivername(p->usrdevicename), p->usrdeviceunit); + + p->fs_position = j; + + j += ((strlen(bdrivername(p->usrdevicename)) + (p->usrdeviceunit > 9 ? 2 : 1) + 1)); + } + wrefresh(mid_w); + + wmove(lower_w, 0, 0); + wrefresh(lower_w); + + curses_ready = 1; +} + +/*---------------------------------------------------------------------------* + * curses menu for fullscreen command mode + *---------------------------------------------------------------------------*/ +void +do_menu(void) +{ + static char *menu[WMITEMS] = + { + "1 - (D)isplay refresh", + "2 - (H)angup (choose a channel)", + "3 - (R)eread config file", + "4 - (Q)uit the program", + }; + + WINDOW *menu_w; + int c; + int mpos; + fd_set set; + struct timeval timeout; + + /* create a new window in the lower screen area */ + + if((menu_w = newwin(WMENU_HGT, WMENU_LEN, WMENU_POSLN, WMENU_POSCO )) == NULL) + { + log(LL_WRN, "ERROR, curses init menu window!"); + return; + } + + /* create a border around the window */ + + box(menu_w, '|', '-'); + + /* add a title */ + + wstandout(menu_w); + mvwaddstr(menu_w, 0, (WMENU_LEN / 2) - (strlen(WMENU_TITLE) / 2), WMENU_TITLE); + wstandend(menu_w); + + /* fill the window with the menu options */ + + for(mpos=0; mpos <= (WMITEMS-1); mpos++) + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + + /* highlight the first menu option */ + + mpos = 0; + wstandout(menu_w); + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + wstandend(menu_w); + + /* input loop */ + + for(;;) + { + wrefresh(menu_w); + + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + timeout.tv_sec = WMTIMEOUT; + timeout.tv_usec = 0; + + /* if no char is available within timeout, exit menu*/ + + if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0) + goto mexit; + + c = wgetch(menu_w); + + switch(c) + { + case ' ': + case '\t': /* hilite next option */ + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + mpos++; + if(mpos >= WMITEMS) + mpos = 0; + wstandout(menu_w); + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + wstandend(menu_w); + break; + + case ('0'+WREFRESH+1): /* display refresh */ + case 'D': + case 'd': + wrefresh(curscr); + goto mexit; + + case ('0'+WQUIT+1): /* quit program */ + case 'Q': + case 'q': + do_exit(0); + goto mexit; + + case ('0'+WHANGUP+1): /* hangup connection */ + case 'H': + case 'h': + display_chans(); + goto mexit; + + case ('0'+WREREAD+1): /* reread config file */ + case 'R': + case 'r': + rereadconfig(42); + goto mexit; + + case '\n': + case '\r': /* exec highlighted option */ + switch(mpos) + { + case WREFRESH: + wrefresh(curscr); + break; + + case WQUIT: + do_exit(0); + break; + + case WHANGUP: + display_chans(); + break; + + case WREREAD: + rereadconfig(42); + break; + } + goto mexit; + break; + + default: + goto mexit; + break; + } + } + +mexit: + /* delete the menu window */ + + delwin(menu_w); + + /* re-display the original lower window contents */ + + touchwin(lower_w); + wrefresh(lower_w); +} + +/*---------------------------------------------------------------------------* + * display the charge in units + *---------------------------------------------------------------------------*/ +void +display_charge(cfg_entry_t *cep) +{ + mvwprintw(upper_w, CHPOS(cep), H_UNITS, "%d", cep->charge); + wclrtoeol(upper_w); + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * display the calculated charge in units + *---------------------------------------------------------------------------*/ +void +display_ccharge(cfg_entry_t *cep, int units) +{ + mvwprintw(upper_w, CHPOS(cep), H_UNITS, "(%d)", units); + wclrtoeol(upper_w); + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * display accounting information + *---------------------------------------------------------------------------*/ +void +display_acct(cfg_entry_t *cep) +{ + mvwprintw(upper_w, CHPOS(cep), H_OUT, "%-10d", cep->outbytes); + mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "%-4d", cep->outbps); + mvwprintw(upper_w, CHPOS(cep), H_IN, "%-10d", cep->inbytes); + mvwprintw(upper_w, CHPOS(cep), H_INBPS, "%-4d", cep->inbps); + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * display connect information + *---------------------------------------------------------------------------*/ +void +display_connect(cfg_entry_t *cep) +{ + char buffer[256]; + + /* remote telephone number */ + + if(aliasing) + { + if(cep->direction == DIR_IN) + sprintf(buffer, "%s", get_alias(cep->real_phone_incoming)); + else + sprintf(buffer, "%s", get_alias(cep->remote_phone_dialout)); + } + else + { + if(cep->direction == DIR_IN) + sprintf(buffer, "%s/%s", cep->name, cep->real_phone_incoming); + else + sprintf(buffer, "%s/%s", cep->name, cep->remote_phone_dialout); + } + + buffer[H_IFN - H_TELN - 1] = '\0'; + + mvwprintw(upper_w, CHPOS(cep), H_TELN, "%s", buffer); + + /* interface */ + + mvwprintw(upper_w, CHPOS(cep), H_IFN, "%s%d ", + bdrivername(cep->usrdevicename), cep->usrdeviceunit); + + mvwprintw(upper_w, CHPOS(cep), H_IO, + cep->direction == DIR_OUT ? "out" : "in"); + + mvwprintw(upper_w, CHPOS(cep), H_OUT, "-"); + mvwprintw(upper_w, CHPOS(cep), H_OUTBPS, "-"); + mvwprintw(upper_w, CHPOS(cep), H_IN, "-"); + mvwprintw(upper_w, CHPOS(cep), H_INBPS, "-"); + + if(do_bell) + display_bell(); + + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * erase line at disconnect time + *---------------------------------------------------------------------------*/ +void +display_disconnect(cfg_entry_t *cep) +{ + wmove(upper_w, CHPOS(cep), + H_TELN); + wclrtoeol(upper_w); + wrefresh(upper_w); + + if(do_bell) + display_bell(); + +} + +/*---------------------------------------------------------------------------* + * display interface up/down information + *---------------------------------------------------------------------------*/ +void +display_updown(cfg_entry_t *cep, int updown) +{ + if(updown) + wstandend(mid_w); + else + wstandout(mid_w); + + mvwprintw(mid_w, 0, cep->fs_position, "%s%d ", + bdrivername(cep->usrdevicename), cep->usrdeviceunit); + + wstandend(mid_w); + wrefresh(mid_w); +} + +/*---------------------------------------------------------------------------* + * display interface up/down information + *---------------------------------------------------------------------------*/ +void +display_l12stat(int controller, int layer, int state) +{ + if(controller > ncontroller) + return; + if(!(layer == 1 || layer == 2)) + return; + + if(state) + wstandout(upper_w); + else + wstandend(upper_w); + + if(layer == 1) + { + mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1"); + if(!state) + mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2"); + } + else if(layer == 2) + { + mvwprintw(upper_w, (controller*2)+1, H_TEI+2, "2"); + if(state) + mvwprintw(upper_w, (controller*2)+1, H_TEI+1, "1"); + } + + wstandend(upper_w); + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * display TEI + *---------------------------------------------------------------------------*/ +void +display_tei(int controller, int tei) +{ + if(controller > ncontroller) + return; + + if(tei == -1) + mvwprintw(upper_w, controller*2, H_TEI, "---"); + else + mvwprintw(upper_w, controller*2, H_TEI, "%3d", tei); + + wrefresh(upper_w); +} + +/*---------------------------------------------------------------------------* + * display bell :-) + *---------------------------------------------------------------------------*/ +void +display_bell(void) +{ + static char bell[1] = { 0x07 }; + write(STDOUT_FILENO, &bell[0], 1); +} + +/*---------------------------------------------------------------------------* + * display channel information for shutdown + *---------------------------------------------------------------------------*/ +void +display_chans(void) +{ + char buffer[80]; + int i; + int cnt = 0; + WINDOW *chan_w; + int nlines, ncols, pos_x, pos_y; + fd_set set; + struct timeval timeout; + cfg_entry_t *cep = NULL; + + /* need this later to close the connection */ + struct ctlr_chan { + int cntl; + int chn; + } *cc = NULL; + + for (i = 0; i < ncontroller; i++) + { + if((get_controller_state(i)) != CTRL_UP) + continue; + if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN) + cnt++; + if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN) + cnt++; + } + + if(cnt > 0) + { + if ((cc = (struct ctlr_chan *)malloc (cnt * + sizeof (struct ctlr_chan))) == NULL) + { + return; + } + nlines = cnt + 4; + ncols = 60; + } + else + { + nlines = 5; + ncols = 22; + } + + pos_y = WMENU_POSLN + 4; + pos_x = WMENU_POSCO + 10; + + /* create a new window in the lower screen area */ + + if((chan_w = newwin(nlines, ncols, pos_y, pos_x )) == NULL) + { + log(LL_WRN, "ERROR, curses init channel window!"); + if (cnt > 0) + free(cc); + return; + } + + /* create a border around the window */ + + box(chan_w, '|', '-'); + + /* add a title */ + + wstandout(chan_w); + mvwaddstr(chan_w, 0, (ncols / 2) - (strlen("Channels") / 2), "Channels"); + wstandend(chan_w); + + /* no active channels */ + if (cnt == 0) + { + mvwaddstr(chan_w, 2, 2, "No active channels"); + wrefresh(chan_w); + sleep(1); + + /* delete the channels window */ + + delwin(chan_w); + return; + } + + nlines = 2; + ncols = 1; + + for (i = 0; i < ncontroller; i++) + { + if((get_controller_state(i)) != CTRL_UP) + continue; + + if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN) + { + sprintf(buffer, "%d - Controller %d channel %s", ncols, i, "B1"); + mvwaddstr(chan_w, nlines, 2, buffer); + cc[ncols - 1].cntl = i; + cc[ncols - 1].chn = CHAN_B1; + nlines++; + ncols++; + } + if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN) + { + sprintf(buffer, "%d - Controller %d channel %s", ncols, i, "B2"); + mvwaddstr(chan_w, nlines, 2, buffer); + cc[ncols - 1].cntl = i; + cc[ncols - 1].chn = CHAN_B2; + nlines++; + ncols++; + } + } + + for(;;) + { + wrefresh(chan_w); + + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + timeout.tv_sec = WMTIMEOUT; + timeout.tv_usec = 0; + + /* if no char is available within timeout, exit menu*/ + + if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0) + break; + + ncols = wgetch(chan_w); + + if (!(isdigit(ncols))) + { + display_bell(); + continue; + } + + nlines = ncols - '0'; + + if ((nlines == 0) || (nlines > cnt)) + { + display_bell(); + continue; + } + + if((cep = get_cep_by_cc(cc[nlines-1].cntl, cc[nlines-1].chn)) + != NULL) + { + log(LL_CHD, "%05d %s manual disconnect (fullscreen menu)", cep->cdid, cep->name); + cep->hangup = 1; + break; + } + } + + free(cc); + + /* delete the channels window */ + + delwin(chan_w); +} + +#endif + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/dial.c b/usr.sbin/i4b/isdnd/dial.c new file mode 100644 index 0000000..4308f98 --- /dev/null +++ b/usr.sbin/i4b/isdnd/dial.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - dial handling routines + * ----------------------------------- + * + * $Id: dial.c,v 1.6 1998/12/05 18:03:09 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:06:36 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +/*---------------------------------------------------------------------------* + * select the first remote number to dial according to the + * dial strategy + *---------------------------------------------------------------------------*/ +void +select_first_dialno(cfg_entry_t *cep) +{ + int i, j; + + if(cep->remote_numbers_count < 1) + { + log(LL_ERR, "select_first_dialno: remote_numbers_count < 1!"); + return; + } + + if(cep->remote_numbers_count == 1) + { + strcpy(cep->remote_phone_dialout, cep->remote_numbers[0].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_first_dialno: only one no, no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = 0; + return; + } + + if(cep->remote_numbers_handling == RNH_FIRST) + { + strcpy(cep->remote_phone_dialout, cep->remote_numbers[0].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_first_dialno: use first, no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = 0; + return; + } + + i = cep->last_remote_number; + + for(j = cep->remote_numbers_count; j > 0; j--) + { + if(cep->remote_numbers[i].flag == RNF_SUCC) + { + if(cep->remote_numbers_handling == RNH_LAST) + { + strcpy(cep->remote_phone_dialout, cep->remote_numbers[i].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_first_dialno: use last, no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = i; + return; + } + else + { + if(++i >= cep->remote_numbers_count) + i = 0; + + strcpy(cep->remote_phone_dialout, cep->remote_numbers[i].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_first_dialno: use next, no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = i; + return; + } + } + + if(++i >= cep->remote_numbers_count) + i = 0; + } + strcpy(cep->remote_phone_dialout, cep->remote_numbers[0].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_first_dialno: no last found (use 0), no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = 0; +} + +/*---------------------------------------------------------------------------* + * select next remote number to dial (last was unsuccesfull) + *---------------------------------------------------------------------------*/ +void +select_next_dialno(cfg_entry_t *cep) +{ + if(cep->remote_numbers_count < 1) + { + log(LL_ERR, "select_next_dialno: remote_numbers_count < 1!"); + return; + } + + if(cep->remote_numbers_count == 1) + { + strcpy(cep->remote_phone_dialout, cep->remote_numbers[0].number); + DBGL(DL_DIAL, (log(LL_DBG, "select_next_dialno: only one no, no = %s", cep->remote_phone_dialout))); + cep->last_remote_number = 0; + return; + } + + /* mark last try as bad */ + + cep->remote_numbers[cep->last_remote_number].flag = RNF_IDLE; + + /* next one to try */ + + cep->last_remote_number++; + + if(cep->last_remote_number >= cep->remote_numbers_count) + cep->last_remote_number = 0; + + strcpy(cep->remote_phone_dialout, cep->remote_numbers[cep->last_remote_number].number); + + DBGL(DL_DIAL, (log(LL_DBG, "select_next_dialno: index=%d, no=%s", + cep->last_remote_number, + cep->remote_numbers[cep->last_remote_number].number))); +} + +/*---------------------------------------------------------------------------* + * dial succeded, store this number as the last successful + *---------------------------------------------------------------------------*/ +void +select_this_dialno(cfg_entry_t *cep) +{ + cep->remote_numbers[cep->last_remote_number].flag = RNF_SUCC; + + DBGL(DL_DIAL, (log(LL_DBG, "select_this_dialno: index = %d, no = %s", + cep->last_remote_number, + cep->remote_numbers[cep->last_remote_number].number))); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/exec.c b/usr.sbin/i4b/isdnd/exec.c new file mode 100644 index 0000000..1ed81a1 --- /dev/null +++ b/usr.sbin/i4b/isdnd/exec.c @@ -0,0 +1,280 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * exec.h - supplemental program/script execution + * ---------------------------------------------- + * + * $Id: exec.c,v 1.10 1998/12/05 18:03:11 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:06:49 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +#include <sys/wait.h> +#include <sys/socket.h> +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#define MAX_PIDS 32 + +static struct pid_tab { + pid_t pid; + cfg_entry_t *cep; +} pid_tab[MAX_PIDS]; + +/*---------------------------------------------------------------------------* + * SIGCHLD signal handler + *---------------------------------------------------------------------------*/ +void +sigchild_handler(int sig) +{ + int retstat; + register int i; + pid_t pid; + + if((pid = waitpid(-1, &retstat, WNOHANG)) <= 0) + { + log(LL_ERR, "ERROR, waitpid: %s", strerror(errno)); + do_exit(1); + } + else + { + if(WIFEXITED(retstat)) + { + DBGL(DL_PROC, (log(LL_DBG, "normal child (pid=%d) termination, exitstat = %d", + pid, WEXITSTATUS(retstat)))); + } + else if(WIFSIGNALED(retstat)) + { + if(WCOREDUMP(retstat)) + log(LL_WRN, "child (pid=%d) termination due to signal %d (coredump)", + pid, WTERMSIG(retstat)); + else + log(LL_WRN, "child (pid=%d) termination due to signal %d", + pid, WTERMSIG(retstat)); + } + } + + /* check if hangup required */ + + for(i=0; i < MAX_PIDS; i++) + { + if(pid_tab[i].pid == pid) + { + if(pid_tab[i].cep->cdid != CDID_UNUSED) + { + DBGL(DL_PROC, (log(LL_DBG, "sigchild_handler: scheduling hangup for cdid %d, pid %d", + pid_tab[i].cep->cdid, pid_tab[i].pid))); + pid_tab[i].cep->hangup = 1; + } + pid_tab[i].pid = 0; + break; + } + } +} + +/*---------------------------------------------------------------------------* + * execute prog as a subprocess and pass an argumentlist + *---------------------------------------------------------------------------*/ +pid_t +exec_prog(char *prog, char **arglist) +{ + char tmp[MAXPATHLEN]; + char path[MAXPATHLEN+1]; + pid_t pid; + int a; + + sprintf(path, "%s/%s", ETCPATH, prog); + + arglist[0] = path; + + tmp[0] = '\0'; + + for(a=1; arglist[a] != NULL; ++a ) + { + strcat(tmp, " " ); + strcat(tmp, arglist[a]); + } + + DBGL(DL_PROC, (log(LL_DBG, "exec_prog: %s, args:%s", path, tmp))); + + switch(pid = fork()) + { + case -1: /* error */ + log(LL_ERR, "ERROR, exec_prog/fork: %s", strerror(errno)); + do_exit(1); + case 0: /* child */ + break; + default: /* parent */ + return(pid); + } + + /* this is the child now */ + + if(execvp(path,arglist) < 0 ) + _exit(127); + + return(-1); +} + +/*---------------------------------------------------------------------------* + * run interface up/down script + *---------------------------------------------------------------------------*/ +int +exec_connect_prog(cfg_entry_t *cep, const char *prog, int link_down) +{ + char *argv[32], **av = argv; + char devicename[MAXPATHLEN], addr[100]; + char *device; + int s; + struct ifreq ifr; + + /* the obvious things */ + device = bdrivername(cep->usrdevicename); + sprintf(devicename, "%s%d", device, cep->usrdeviceunit); + *av++ = (char*)prog; + *av++ = "-d"; + *av++ = devicename; + *av++ = "-f"; + *av++ = link_down ? "down" : "up"; + + /* try to figure AF_INET address of interface */ + addr[0] = '\0'; + memset(&ifr, 0, sizeof ifr); + ifr.ifr_addr.sa_family = AF_INET; + strncpy(ifr.ifr_name, devicename, sizeof(ifr.ifr_name)); + s = socket(AF_INET, SOCK_DGRAM, 0); + if (s >= 0) { + if (ioctl(s, SIOCGIFADDR, (caddr_t)&ifr) >= 0) { + struct sockaddr_in *sin = (struct sockaddr_in *)&ifr.ifr_addr; + strcpy(addr, inet_ntoa(sin->sin_addr)); + *av++ = "-a"; + *av++ = addr; + } + close(s); + } + + /* terminate argv */ + *av++ = NULL; + + return exec_prog((char*)prog, argv); +} + +/*---------------------------------------------------------------------------* + * run answeringmachine application + *---------------------------------------------------------------------------*/ +int +exec_answer(cfg_entry_t *cep) +{ + char *argv[32]; + u_char devicename[MAXPATHLEN]; + int pid; + char *device; + + device = bdrivername(cep->usrdevicename); + + sprintf(devicename, "/dev/i4b%s%d", device, cep->usrdeviceunit); + + argv[0] = cep->answerprog; + argv[1] = "-D"; + argv[2] = devicename; + argv[3] = "-d"; + argv[4] = "unknown"; + argv[5] = "-s"; + argv[6] = "unknown"; + argv[7] = NULL; + + /* if destination telephone number avail, add it as argument */ + + if(*cep->local_phone_incoming) + argv[4] = cep->local_phone_incoming; + + /* if source telephone number avail, add it as argument */ + + if(*cep->real_phone_incoming) + argv[6] = cep->real_phone_incoming; + + if(*cep->display) + { + argv[7] = "-t"; + argv[8] = cep->display; + argv[9] = NULL; + } + + /* exec program */ + + DBGL(DL_PROC, (log(LL_DBG, "exec_answer: prog=[%s]", cep->answerprog))); + + pid = exec_prog(cep->answerprog, argv); + + /* enter pid and conf ptr entry addr into table */ + + if(pid != -1) + { + int i; + + for(i=0; i < MAX_PIDS; i++) + { + if(pid_tab[i].pid == 0) + { + pid_tab[i].pid = pid; + pid_tab[i].cep = cep; + break; + } + } + return(GOOD); + } + return(ERROR); +} + +/*---------------------------------------------------------------------------* + * check if a connection has an outstanding process, if yes, kill it + *---------------------------------------------------------------------------*/ +void +check_and_kill(cfg_entry_t *cep) +{ + int i; + + for(i=0; i < MAX_PIDS; i++) + { + if(pid_tab[i].cep == cep) + { + pid_t kp; + + DBGL(DL_PROC, (log(LL_DBG, "check_and_kill: killing pid %d", pid_tab[i].pid))); + + kp = pid_tab[i].pid; + pid_tab[i].pid = 0; + kill(kp, SIGHUP); + break; + } + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/fsm.c b/usr.sbin/i4b/isdnd/fsm.c new file mode 100644 index 0000000..13d5778 --- /dev/null +++ b/usr.sbin/i4b/isdnd/fsm.c @@ -0,0 +1,446 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * FSM for isdnd + * ------------- + * + * $Id: fsm.c,v 1.15 1998/12/05 18:03:12 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:07:31 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +/* table of state descriptions */ + +static char *state_text[N_STATES] = { + "idle", + "dialing", + "waitdialretry", + "dialretry", + + "pcb-dialing", + "pcb-dialfail", + "pcb-waitcall", + + "acb-waitdisc", + "acb-waitdial", + "acb-dialing", + "acb-dialfail", + + "accepted", + "connected", + "waitdisconnect", + "down", + "alert", + + "Illegal State" +}; + +/* table of event descriptions */ + +static char *event_text[N_EVENTS] = { + + /* incoming messages */ + + "msg-con-ind", + "msg-con-act-ind", + "msg-disc-ind", + "msg-dialout", + + /* local events */ + + "timeout", + "disconnect-req", + "callback-req", + "alert-req", + + /* illegal */ + + "Illegal Event" +}; + +/*---------------------------------------------------------------------------* + * illegal state default action + *---------------------------------------------------------------------------*/ +static void +F_ill(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_ill: Illegal State reached !!!"))); +} + +/*---------------------------------------------------------------------------* + * No change, No action + *---------------------------------------------------------------------------*/ +static void +F_NcNa(cfg_entry_t *cep) +{ +} + +/*---------------------------------------------------------------------------* + * incoming CONNECT, accepting call + *---------------------------------------------------------------------------*/ +static void +F_MCI(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_MCI: tx SETUP_RESP_ACCEPT"))); + sendm_connect_resp(cep, cep->cdid, SETUP_RESP_ACCEPT, 0); + start_timer(cep, TIMEOUT_CONNECT_ACTIVE); +} + +/*---------------------------------------------------------------------------* + * incoming connect active, call is now active + *---------------------------------------------------------------------------*/ +static void +F_MCAI(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_MCAI: Connection active!"))); + + stop_timer(cep); + + if((cep->dialin_reaction == REACT_ANSWER) && + (cep->b1protocol == BPROT_NONE)) + { + exec_answer(cep); + } +} + +/*---------------------------------------------------------------------------* + * timeout + *---------------------------------------------------------------------------*/ +static void +F_TIMO(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_TIMO: Timout occured!"))); + sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + cep->cdid = CDID_UNUSED; +} + +/*---------------------------------------------------------------------------* + * incoming disconnect indication + *---------------------------------------------------------------------------*/ +static void +F_IDIS(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_IDIS: disconnect indication"))); + cep->cdid = CDID_UNUSED; +} + +/*---------------------------------------------------------------------------* + * local disconnect request + *---------------------------------------------------------------------------*/ +static void +F_DRQ(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_DRQ: local disconnect request"))); + sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); +} + +/*---------------------------------------------------------------------------* + * disconnect indication after local disconnect req + *---------------------------------------------------------------------------*/ +static void +F_MDI(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_MDI: disconnect indication, local disconnected"))); + cep->cdid = CDID_UNUSED; +} + +/*---------------------------------------------------------------------------* + * local requested outgoing dial + *---------------------------------------------------------------------------*/ +static void +F_DIAL(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_DIAL: local dial out request"))); + + if(cep->dialrandincr) + cep->randomtime = (random() & RANDOM_MASK) + cep->recoverytime; + + cep->dial_count = 0; + + select_first_dialno(cep); + + sendm_connect_req(cep); +} + +/*---------------------------------------------------------------------------* + * outgoing dial successfull + *---------------------------------------------------------------------------*/ +static void +F_DOK(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_DOK: dial out ok"))); + select_this_dialno(cep); +} + +/*---------------------------------------------------------------------------* + * outgoing dial fail (ST_SUSE !!!) + *---------------------------------------------------------------------------*/ +static void +F_DFL(cfg_entry_t *cep) +{ + cep->last_release_time = time(NULL); + + if(cep->dialouttype == DIALOUT_NORMAL) + { + cep->dial_count++; + + if(cep->dial_count < cep->dialretries) + { + /* inside normal retry cycle */ + + DBGL(DL_STATE, (log(LL_DBG, "F_DFL: dial fail, dial retry"))); + select_next_dialno(cep); + cep->cdid = CDID_RESERVED; + cep->state = ST_DIALRTMRCHD; + return; + } + + /* retries exhausted */ + + if(!cep->usedown) + { + DBGL(DL_STATE, (log(LL_DBG, "F_DFL: dial retry fail, dial retries exhausted"))); + dialresponse(cep, DSTAT_TFAIL); + cep->cdid = CDID_UNUSED; + cep->dial_count = 0; + cep->state = ST_IDLE; + return; + } + + /* interface up/down active */ + + cep->down_retry_count++; + + if(cep->down_retry_count > cep->downtries) + { + /* set interface down */ + DBGL(DL_STATE, (log(LL_DBG, "F_DFL: dial retry cycle fail, setting interface down!"))); + dialresponse(cep, DSTAT_PFAIL); + if_down(cep); + cep->state = ST_DOWN; + } + else + { + /* enter new dial retry cycle */ + DBGL(DL_STATE, (log(LL_DBG, "F_DFL: dial retry cycle fail, enter new retry cycle!"))); + select_next_dialno(cep); + cep->state = ST_DIALRTMRCHD; + } + + cep->dial_count = 0; + cep->cdid = CDID_RESERVED; + } + else /* cdp->dialouttype == DIALOUT_CALLEDBACK */ + { + DBGL(DL_STATE, (log(LL_DBG, "F_DFL: calledback dial done, wait for incoming call"))); + cep->cdid = CDID_RESERVED; + cep->state = ST_PCB_WAITCALL; + } +} + +/*---------------------------------------------------------------------------* + * local requested outgoing dial + *---------------------------------------------------------------------------*/ +static void +F_ACBW(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_ACBW: local callback, wait callback recovery time"))); + + if(cep->dialrandincr) + cep->randomtime = (random() & RANDOM_MASK) + cep->recoverytime; + + cep->dial_count = 0; + + cep->cdid = CDID_RESERVED; +} + +/*---------------------------------------------------------------------------* + * active callback dialout retry (ST_SUSE !!!) + *---------------------------------------------------------------------------*/ +static void +F_ACBR(cfg_entry_t *cep) +{ + cep->dial_count++; + + if(cep->dial_count < cep->dialretries) + { + /* inside normal retry cycle */ + + DBGL(DL_STATE, (log(LL_DBG, "F_ACBR: dial fail, dial retry"))); + select_next_dialno(cep); + cep->cdid = CDID_RESERVED; + cep->state = ST_ACB_DIALFAIL; + return; + } + + /* retries exhausted */ + + if(!cep->usedown) + { + DBGL(DL_STATE, (log(LL_DBG, "F_ACBR: dial retry fail, dial retries exhausted"))); + dialresponse(cep, DSTAT_TFAIL); + cep->cdid = CDID_UNUSED; + cep->dial_count = 0; + cep->state = ST_IDLE; + return; + } + + /* interface up/down active */ + + cep->down_retry_count++; + + if(cep->down_retry_count > cep->downtries) + { + /* set interface down */ + DBGL(DL_STATE, (log(LL_DBG, "F_ACBR: dial retry cycle fail, setting interface down!"))); + dialresponse(cep, DSTAT_PFAIL); + if_down(cep); + cep->state = ST_DOWN; + } + else + { + /* enter new dial retry cycle */ + DBGL(DL_STATE, (log(LL_DBG, "F_ACBR: dial retry cycle fail, enter new retry cycle!"))); + select_next_dialno(cep); + cep->state = ST_ACB_DIALFAIL; + } + + cep->dial_count = 0; + cep->cdid = CDID_RESERVED; +} + +/*---------------------------------------------------------------------------* + * local requested to send ALERT message + *---------------------------------------------------------------------------*/ +static void +F_ALRT(cfg_entry_t *cep) +{ + DBGL(DL_STATE, (log(LL_DBG, "F_ALRT: local send alert request"))); + + cep->alert_time = cep->alert; + + sendm_alert_req(cep); +} + +/*---------------------------------------------------------------------------* + * isdn daemon state transition table + *---------------------------------------------------------------------------*/ +struct state_tab { + void(*func)(cfg_entry_t *cep); /* function to execute */ + int newstate; /* next state */ +} state_tab[N_EVENTS][N_STATES] = { + +/* STATE: ST_IDLE ST_DIAL ST_DIALRTMRCHD ST_DIALRETRY ST_PCB_DIAL ST_PCB_DIALFAIL ST_PCB_WAITCALL ST_ACB_WAITDISC ST_ACB_WAITDIAL ST_ACB_DIAL ST_ACB_DIALFAIL ST_ACCEPTED ST_CONNECTED ST_WAITDISCI ST_DOWN ST_ALERT ST_ILLEGAL */ +/* -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ +/* messages */ +/* EV_MCI */{{F_MCI, ST_ACCEPTED}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_MCI, ST_ACCEPTED}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_MCI, ST_ACCEPTED}, {F_ill, ST_ILL}}, +/* EV_MCAI */{{F_ill, ST_ILL}, {F_DOK, ST_CONNECTED}, {F_ill, ST_ILL}, {F_DOK, ST_CONNECTED}, {F_DOK, ST_CONNECTED}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_DOK, ST_CONNECTED}, {F_ill, ST_ILL}, {F_MCAI,ST_CONNECTED}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_MDI */{{F_ill, ST_ILL}, {F_DFL, ST_SUSE}, {F_ill, ST_ILL}, {F_DFL, ST_SUSE}, {F_DFL, ST_SUSE}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ACBW,ST_ACB_WAITDIAL},{F_ill, ST_ILL}, {F_ACBR, ST_SUSE}, {F_ACBR,ST_SUSE}, {F_IDIS,ST_IDLE}, {F_IDIS,ST_IDLE}, {F_MDI, ST_IDLE}, {F_ill, ST_ILL}, {F_MDI, ST_IDLE}, {F_ill, ST_ILL}}, +/* EV_MDO */{{F_DIAL,ST_DIAL}, {F_NcNa,ST_DIAL}, {F_NcNa,ST_DIALRTMRCHD},{F_NcNa,ST_DIALRETRY}, {F_NcNa,ST_PCB_DIAL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, + +/* local requests */ +/* EV_TIMO */{{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_TIMO,ST_IDLE}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_DRQ */{{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_DRQ, ST_WAITDISCI}, {F_NcNa,ST_WAITDISCI}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_CBRQ */{{F_NcNa,ST_ACB_WAITDIAL},{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_NcNa,ST_ACB_WAITDIAL},{F_NcNa, ST_ACB_DIAL}, {F_NcNa,ST_ACB_DIALFAIL},{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, +/* EV_ALRT */{{F_ALRT,ST_ALERT}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}}, + +/* illegal */ + +/* EV_ILL */{{F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}, {F_ill, ST_ILL}} +}; + +/*---------------------------------------------------------------------------* + * event handler + *---------------------------------------------------------------------------*/ +void +next_state(cfg_entry_t *cep, int event) +{ + int currstate, newstate; + + if(event > N_EVENTS) + { + log(LL_ERR, "FSM: event > N_EVENTS"); + do_exit(1); + } + + currstate = cep->state; + + if(currstate > N_STATES) + { + log(LL_ERR, "FSM: currstate > N_STATES"); + do_exit(1); + } + + newstate = state_tab[event][currstate].newstate; + + if(newstate > N_STATES) + { + log(LL_ERR, "FSM: newstate > N_STATES"); + do_exit(1); + } + + if(newstate != ST_SUSE) + { + DBGL(DL_STATE, (log(LL_DBG, "FSM event [%s]: [%s => %s]", event_text[event], + state_text[currstate], + state_text[newstate]))); + } + + (*state_tab[event][currstate].func)(cep); + + if(newstate == ST_ILL) + { + log(LL_ERR, "FSM ILLEGAL STATE, event=%s: oldstate=%s => newstate=%s]", + event_text[event], + state_text[currstate], + state_text[newstate]); + } + + if(newstate == ST_SUSE) + { + DBGL(DL_STATE, (log(LL_DBG, "FSM (SUSE) event [%s]: [%s => %s]", event_text[event], + state_text[currstate], + state_text[cep->state]))); + } + else + { + cep->state = newstate; + } +} + +/*---------------------------------------------------------------------------* + * return pointer to current state description + *---------------------------------------------------------------------------*/ +char * +printstate(cfg_entry_t *cep) +{ + return((char *) state_text[cep->state]); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/isdnd.8 b/usr.sbin/i4b/isdnd/isdnd.8 new file mode 100644 index 0000000..9913487 --- /dev/null +++ b/usr.sbin/i4b/isdnd/isdnd.8 @@ -0,0 +1,419 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdnd.8,v 1.20 1998/12/18 09:47:09 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 12 21:13:59 1998] +.\" +.Dd November 3, 1998 +.Dt isdnd 8 +.Sh NAME +.Nm isdnd +.Nd isdn4bsd ISDN connection management daemon +.Sh SYNOPSIS +.Nm isdnd +.Op Fl b +.Op Fl c Ar configfile +.Op Fl d Ar debuglevel +.Op Fl f +.Op Fl F +.Op Fl l +.Op Fl L Ar logfile +.Op Fl P +.Op Fl r Ar device +.Op Fl s Ar facility +.Op Fl t Ar terminaltype +.Op Fl u Ar charging unit length +.Op Fl m +.Sh DESCRIPTION +.Nm Isdnd +is the isdn4bsd package demon which manages all ISDN related connection +and disconnection of ISDN devices supported by the package. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl b +Bell: in full-screen mode, ring the bell when connecting +or disconnecting a call. +.It Fl c +Use +.Ar configfile +as the name of the runtime configuration filename for +.Nm isdnd +instead of the default file +.Li /etc/isdn/isdnd.rc . +.It Fl d +If debugging support is compiled into +.Nm isdnd +this option is used to specify the debugging level, or better which kind +of debugging messages are displayed. The debugging level is the sum of the +following values: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar 0x001 +general debugging. +.It Ar 0x002 +rates calculation. +.It Ar 0x004 +timing calculations. +.It Ar 0x008 +state transitions. +.It Ar 0x010 +retry handling. +.It Ar 0x020 +dialing. +.It Ar 0x040 +process handling. +.It Ar 0x080 +isdn4bsd kernel i/o calls. +.It Ar 0x100 +controller and channel busy/free messages. +.El +.Pp +The value can be specified in any number base supported by the +.Xr sscanf 3 +library routine. +.Pp +In addition, this option accepts also the character 'n' as an argument to +disable displaying debug messages on the full-screen display. +.Pp +.It Fl f +Specifying this option causes +.Nm isdnd +to enter the full-screen mode of operation. When operating in this mode, +entering the control character +.Em Control-L +causes the display to be refreshed and entering +.Em Carriage-Return +or +.Em Enter +will pop-up a command window. Because the +.Nm +daemon will not listen to messages while the command window is active, +this command window will disappear automatically after 5 seconds without +any command key press. +.Pp +While the command window is active, +.Em Tab +or +.Em Space +advances to the next menu item. To execute a command, press +.Em Return +or +.Em Enter +for the highlighted menu item, or enter the number corresponding to the +item to be executed or enter the capitalized character in the menu item +description. +.It Fl l +If this option is set, logging is not done via the +.Xr syslogd 8 +facility but instead is appended to a file. +.It Fl L +Specifies the name of the logfile which is used when the option +.Em -l +is set. +.It Fl P +This option prints out the parsed and verified isdnd configuration in the same +format as the isdnd.rc file. This output can be used as an isdnd.rc file. This +feature is especially useful when debugging an isdnd.rc file to see, what the +default settings of options are when they are not set in the isdnd.rc input +file. +.Pp +The +.Nm +exits after the printout is done. +.It Fl F +This option prevents +.Nm isdnd +to detach from the controlling tty and become a daemon. +.It Fl r +In conjunction with the +.Fl t +option, +.Ar device +specifies a terminal device which becomes the controlling tty for +.Nm isdnd +and on which the full-screen mode output is displayed. +.It Fl s +This option may be used to specify the logging facility in case +.Xr syslog 3 +logging is configured and another facility than the default LOCAL0 +facility shall be used. The facility is to be specified as an integer in +the range 0-11 or 16-23 (see the file /usr/include/syslog.h). +.It Fl t +In conjunction with the +.Fl f +and +.Fl r +options, +.Ar terminaltype +specifies a terminal type or termcap entry name (such as vt220) for the device +used for +.Nm isdnd +full-screen output. This is useful if an unused (no getty running) tty line is +used for full-screen output for which no +.Li TERM +environment variable exists. +.It Fl u +Specifies the length of a charging unit in case the config file entry +keyword +.Em unitlenghtsrc +is set to +.Em cmdl . +.It Fl m +If the isdn daemon is compiled with local or remote monitoring support, +this option disables all monitoring access. It overrides the config +file option +.Em monitor-allowed . +.El +.Pp +.Sh INTERACTION WITH THE KERNEL +.Nm Isdnd +communicates with the kernel part of isdn4bsd by receiving status and +event messages ( +.Xr read 2 +from device /dev/i4b ) and by transmitting commands and responses ( +.Xr ioctl 2 +from device /dev/i4b ). +.Pp +The messages and message parameters are documented in the include +file +.Em /usr/include/machine/i4b_ioctl.h . +.Pp +Supported command and response messages (ioctl's) to the kernel are: +.Bl -tag -width Ds -compact -offset indent +.It Ar I4B_CDID_REQ +Request a unique Call Description IDentifier (cdid) which identifies +uniquely a single interaction of the local D channel with the exchange. +.It Ar I4B_CONNECT_REQ +Actively request a call setup to a remote ISDN subscriber. +.It Ar I4B_CONNECT_RESP +Respond to an incoming call, either accept, reject or ignore it. +.It Ar I4B_DISCONNECT_REQ +Actively terminate a connection. +.It Ar I4B_CTRL_INFO_REQ +Request information about an installed ISDN controller card. +.It Ar I4B_DIALOUT_RESP +Give information about call setup to driver who requested dialing out. +.It Ar I4B_TIMEOUT_UPD +Update the kernels timeout value(s) in case of dynamically calculated +shorthold mode timing changes. +.It Ar I4B_UPDOWN_IND +Inform the kernel userland drivers about interface soft up/down status +changes. +.It Ar I4B_CTRL_DOWNLOAD +Download firmware to active card(s). +.It Ar I4B_ACTIVE_DIAGNOSTIC +Return diagnostic information from active cards. +.El +.Pp +.Pp +Supported status and event messages from the kernel are: +.Bl -tag -width Ds -compact -offset indent +.It Ar MSG_CONNECT_IND +An incoming call from a remote ISDN user is indicated. +.It Ar MSG_CONNECT_ACTIVE_IND +After an incoming call has been accepted locally or an outgoing call has +been accepted by a remote, the exchange signaled an active connection +and the corresponding B-channel is switched through. +.It Ar MSG_DISCONNECT_IND +A call was terminated. +.It Ar MSG_DIALOUT_IND +A userland interface driver requests the daemon to dial out (typically a +network interface when a packet arrives in its send queue). +.It Ar MSG_IDLE_TIMEOUT_IND +A call was terminated by the isdn4bsd kernel driver because a B-channel +idle timeout occurred. +.It Ar MSG_ACCT_IND +Accounting information from a network driver. +.It Ar MSG_CHARGING_IND +Charging information from the kernel. +.El +.Pp +.Ss OUTGOING CALLS +Currently the only possibility to trigger an outgoing call is that an +isdn4bsd network driver +.Em (ipr<n>) +sends a +.Em MSG_DIALOUT_IND +to the +.Nm +daemon. +.Pp +The daemon requests a new CDID from the kernel by using the +.Em I4B_CDID_REQ +ioctl message, this CDID is now used in all interactions with the kernel +to identify this single call until a disconnect occurs. +.Pp +After getting the CDID, the daemon looks up several additional information +in its entry section of the configuration corresponding to that connection +and issues a +.Em I4B_CONNECT_REQ +ioctl message to the kernel. The kernel now dials the remote side and +if the remote side accepts the call, the kernel sends a +.Em MSG_CONNECT_ACTIVE_IND +to the daemon. +.Pp +The call is terminated by either the local site timing out or the remote +side hanging up the connection or the local side actively sending a +.Em DISCONNECT_REQ +ioctl message, both events are signaled to the +.Nm +by the kernel sending the +.Em DISCONNECT_IND +message and the CDID corresponding to the call is no longer valid. +.Pp +.Ss INCOMING CALLS +Incoming calls are signaled to the +.Nm +by the kernel transmitting the +.Em MSG_CONNECT_IND +message to the daemon. +.Pp +With the information contained in this message, the +.Nm +searches the entry section of its configuration database and if a match is +found, it accepts or rejects the call or, of no match is found, it ignores the +call - all by issuing a +.Em I4B_CONNECT_RESP +ioctl message with the appropriate parameters to the kernel. +.Pp +In case the daemon decided to accept the message, the kernel signal the then +active connection by sending a +.Em MSG_CONNECT_ACTIVE_IND +message to the daemon. +.Pp +The call is terminated by either the local site timing out or the remote +side hanging up the connection or the local side actively sending a +.Em DISCONNECT_REQ +ioctl message, both events are signaled to the +.Nm +by the kernel sending the +.Em DISCONNECT_IND +message and the CDID corresponding to the call is no longer valid. +.Pp + +.Sh SIGNALS + +Sending a HUP signal to +.Nm +causes all open connections to be terminated and the configuration file is +reread. In case aliasfile handling was enabled, the aliasfile is also +reread. + +Sending a USR1 signal to +.Nm +causes the accounting file and the logfile (if logging to a file is used +instead of logging via the +.Xr syslog 3 +facility) to be closed and reopened to make logfile rotation possible. + +.Sh ENVIRONMENT +The following environment variables affect the execution of +.Nm isdnd : +.Bl -tag -width Ds +.It Ev TERM +The terminal type when running in full-screen display mode. +See +.Xr environ 7 +for more information. +.El + +.Sh FILES +.Bl -tag -width /etc/isdn/isdnd.rates -compact +.It Pa /dev/i4b +The device-file used to communicate with the kernel ISDN driver subsystem. + +.It Pa /var/log/messages +A record of the actions in case of syslogd logging support. + +.It Pa /var/log/isdnd.acct +The default accounting information filename (if accounting is configured). + +.It Pa /var/log/isdnd.log +The default logging filename (if logging to a file is configured). + +.It Pa /var/run/isdnd.pid +The process id of the isdn daemon (also known as "lockfile" to isdnd, preventing multiple invocations of it). + +.It Pa /usr/local/lib/isdn +.It Pa /etc/isdn +The directory where isdnd expects some supplementary data files and programs +for telephone answering support. + +.It Pa /etc/isdn/isdnd.rc +The default runtime configuration file. + +.It Pa /etc/isdn/isdnd.rates +The default unit charging rates specification file. + +.It Pa /etc/isdn/isdntel.alias +The default table (if aliasing is enabled) to convert phone number to caller's name. +.El + +.Sh EXAMPLES +For a first try, the following command should be used to start +.Nm +in foreground mode for better debugging the configuration setup: +.Bd -literal -offset indent +isdnd -d0xf9 -F +.Ed +.Pp +This will start isdnd with reasonable debugging settings and produce +output on the current terminal. +.Nm Isdnd +can then be terminated by entering Control-C. +.Pp +Another example, the command: +.Bd -literal -offset indent +isdnd -d0xf9 -f -r /dev/ttyv3 -t vt100 +.Ed +.Pp +will start +.Nm isdnd +with reasonable debugging messages enabled, full-screen mode of operation, +full-screen display redirected to /dev/ttyv03 and using a termcap entry +for vt100 on this display. + +.Sh DIAGNOSTICS +Exit status is 0 on success, 1 on error. +.Pp + +.Sh SEE ALSO +.Xr syslogd 8 , +.Xr isdntrace 8 , +.Xr isdntel 8 , +.Xr isdnd.rc 5 , +.Xr isdnd.rates 5 , +.Xr i4bisppp 4 , +.Xr i4bipr 4 + +.Sh BUGS +Still one or more left. + +.Sh AUTHOR +The +.Nm +daemon and this manual page were written by Hellmuth Michaelis. He can +be contacted at hm@kts.org or hm@hcs.de. diff --git a/usr.sbin/i4b/isdnd/isdnd.acct.5 b/usr.sbin/i4b/isdnd/isdnd.acct.5 new file mode 100644 index 0000000..9329e80 --- /dev/null +++ b/usr.sbin/i4b/isdnd/isdnd.acct.5 @@ -0,0 +1,108 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdnd.acct.5,v 1.6 1998/12/05 18:03:18 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:09:33 1998] +.\" +.Dd September 11, 1998 +.Dt isdnd.acct 5 +.Sh NAME +.Nm isdnd.acct +.Nd isdn4bsd ISDN management daemon accounting file format +.Sh DESCRIPTION +The file +.Pa isdnd.acct +contains accounting information which is written if the variable +.Em useacctfile +in the +.Xr isdnd 8 +configuration file +.Xr isdnd.rc 5 +is set to +.Em on +and charging information transmission has been subscribed for the +ISDN connection (AOCD or AOCE). +.Pp +If the variable +.Em acctall +is set to +.Em on , +accounting information is written even if the local site was not charged +or no charging information is available or is not subscribed. +.Pp +The general format of an accounting line is a follows: +.Pp +.Dl FROM - UNTIL NAME UNITS (SECONDS) (INBYTES/OUTBYTES) +.Pp +.Em FROM +is the time the connection was established in the format +.Dl Day:Month:Year Hour:Minutes:seconds +.Pp +.Em UNTIL +is the time the connection was closed. The format is the same as +described for +.Em FROM +above. +.Pp +.Em NAME +is the symbolic name got from the +.Em name +entry of the +.Xr isdnd.rc 5 +config file for this connection. +.Pp +.Em UNITS +is the amount of charging units billed for the connection. +.Pp +.Em SECONDS +is the number of seconds the connection lasted. +.Pp +.Em INBYTES +and +.Em OUTBYTES +is the (optional) number of bytes that were transferred. + +.Sh FILES +.Bl -tag -width /var/log/isdnd.acct -compact +.It Pa /var/log/isdnd.acct +The default accounting information file for the +.Nm isdnd +ISDN daemon. + +.Sh EXAMPLES +This is a typical accounting line: +.Pp +.Dl 12.06.97 10:41:37 - 12.06.97 10:45:18 GROGGY 2 (65) (4711/1147) + +.Sh SEE ALSO +.Xr isdnd 8 , +.Xr isdnd.rc 5 + +.Sh AUTHOR +The +.Xr isdnd 8 +daemon and this manual page were written by Hellmuth Michaelis. +He can be contacted at hm@kts.org or hm@hcs.de. + diff --git a/usr.sbin/i4b/isdnd/isdnd.h b/usr.sbin/i4b/isdnd/isdnd.h new file mode 100644 index 0000000..009a2dd --- /dev/null +++ b/usr.sbin/i4b/isdnd/isdnd.h @@ -0,0 +1,754 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - main header file + * ----------------------------- + * + * $Id: isdnd.h,v 1.56 1998/12/16 13:39:46 hm Exp $ + * + * last edit-date: [Mon Dec 14 10:06:39 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _ISDND_H_ +#define _ISDND_H_ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <strings.h> +#include <ctype.h> +#include <syslog.h> +#include <regex.h> + +#ifdef USE_CURSES +#include <curses.h> +#endif + +#include <fcntl.h> +#include <errno.h> +#include <signal.h> + +#include <sys/param.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ioctl.h> + +#ifdef USE_RTPRIO +#include <sys/rtprio.h> +#endif + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> + +#include "config.h" /* compile time configuration */ +#include "pathnames.h" /* location of files */ +#include "alias.h" /* alias file processing */ + +/*---------------------------------------------------------------------------* + * some general definitions + *---------------------------------------------------------------------------*/ +#define GOOD 0 /* general "good" or "ok" return*/ +#define ERROR (-1) /* general error return */ +#define WARNING (-2) /* warning return */ +#define INVALID (-1) /* an invalid integer */ + +/*---------------------------------------------------------------------------* + * misc + *---------------------------------------------------------------------------*/ +#define RTPRIO_NOTUSED (-1) /* rtprio is not used for isdnd */ + +/*---------------------------------------------------------------------------* + * debug flag bits + *---------------------------------------------------------------------------*/ +#define DL_MSG 0x0001 /* general debug messages */ +#define DL_RATES 0x0002 /* messages related to rates */ +#define DL_TIME 0x0004 /* messages related to timing */ +#define DL_STATE 0x0008 /* messages related to states changes */ +#define DL_RCVRY 0x0010 /* messages related to dial recovery */ +#define DL_DIAL 0x0020 /* messages related to dial recovery */ +#define DL_PROC 0x0040 /* messages related to process handling */ +#define DL_DRVR 0x0080 /* messages related to kernel i4b msg i/o*/ +#define DL_CNST 0x0100 /* messages related to controller state */ + +#ifdef DEBUG +#define DBGL(cond, dolog) if(cond & debug_flags) dolog +#else +#define DBGL(cond, dolog) +#endif + +/*---------------------------------------------------------------------------* + * curses fullscreen display definitions + *---------------------------------------------------------------------------*/ + +/* window dimensions */ +#define UPPER_B 2 /* upper window start */ + +/* horizontal positions for upper window */ +#define H_CNTL 0 /* controller */ +#define H_TEI 2 /* TEI */ +#define H_CHAN (H_TEI+4) /* channel */ +#define H_TELN (H_CHAN+2) /* telephone number */ +#define H_IFN (H_TELN+23) /* interfacename */ +#define H_IO (H_IFN+7) /* incoming or outgoing */ +#define H_OUT (H_IO+4) /* # of bytes out */ +#define H_OUTBPS (H_OUT+11) /* bytes per second out */ +#define H_IN (H_OUTBPS+5) /* # of bytes in */ +#define H_INBPS (H_IN+11) /* bytes per second in */ +#define H_UNITS (H_INBPS+6) /* # of charging units */ + +/* fullscreen mode menu window */ +#define WMENU_LEN 35 /* width of menu window */ +#define WMENU_TITLE "Command" /* title string */ +#define WMENU_POSLN 10 /* menu position, line */ +#define WMENU_POSCO 5 /* menu position, col */ +#define WMITEMS 4 /* no of menu items */ +#define WMENU_HGT (WMITEMS + 4) /* menu window height */ + +#define WREFRESH 0 +#define WHANGUP 1 +#define WREREAD 2 +#define WQUIT 3 + +#define WMTIMEOUT 5 /* timeout in seconds */ + +/*---------------------------------------------------------------------------* + * charging rates + *---------------------------------------------------------------------------*/ +#define NDAYS 7 /* number of days in a week */ +#define NRATES 4 /* number of rate structures supported */ + +/* struct for rates - each day has one or more */ +struct rates +{ + int start_hr; /* hour at which this rate starts, e.g. 12 */ + int start_min; /* minute of start ... */ + int end_hr; /* hour at which this rate ends, e.g. 19 */ + int end_min; /* minute of end ... */ + int rate; /* how long can I telephone at this price, seconds */ + struct rates *next; +}; + +/*---------------------------------------------------------------------------* + * the internal identifiers for isdnd log levels. CAUTION: this has to stay + * in sync with the loglevel to text and sysloglevel table in log.c !! + *---------------------------------------------------------------------------*/ +enum logids +{ + LL_ERR, /* error conditions - everything which caused an error */ + LL_WRN, /* warning conditions - nonfatal abnormal conditions */ + LL_DMN, /* normal but significant condition - status of daemon */ + LL_CHD, /* informational - everything regarding call handling */ + LL_DBG /* debug messages - everything which helps debugging */ +}; + +/*---------------------------------------------------------------------------* + * state machine events + *---------------------------------------------------------------------------*/ +enum events +{ + /* incoming messages */ + + EV_MCI, /* MSG_CONNECT_IND */ + EV_MCAI, /* MSG_CONNECT_ACTIVE_IND */ + EV_MDI, /* MSG_DISCONNECT_IND */ + EV_MDO, /* MSG_DIALOUT */ + + /* local requests */ + + EV_TIMO, /* timer expired */ + EV_DRQ, /* disconnect request */ + EV_CBRQ, /* callback request */ + EV_ALRT, /* alerting request */ + + /* illegal */ + + EV_ILL /* illegal event */ +}; + +#define N_EVENTS (EV_ILL+1) /* no of possible events */ + +/*---------------------------------------------------------------------------* + * this struct describes the numbers to try to dial out + *---------------------------------------------------------------------------*/ +typedef struct { + char number[TELNO_MAX]; /* remote number to dial */ + int flag; /* usage flag */ +#define RNF_IDLE 0 +#define RNF_SUCC 1 /* last dial was ok */ +} remote_number_t; + +/*---------------------------------------------------------------------------* + * this struct describes numbers allowed to dial in + *---------------------------------------------------------------------------*/ +typedef struct { + char number[TELNO_MAX]; /* calling party number */ +} incoming_number_t; + +/*---------------------------------------------------------------------------* + * this structure describes a prematurely aborted called-back dialout + *---------------------------------------------------------------------------*/ +typedef struct { + int cdid; /* call handle */ + int controller; /* the controller used to dial out */ + int channel; /* the channel assigned to the outgoing call */ + /* XXX - timeout handling and error recovery? */ +} phantom_t; + +/*---------------------------------------------------------------------------* + * this struct describes one complete configuration entry + *---------------------------------------------------------------------------*/ +typedef struct cfg_entry { + + /* ====== filled in at startup configuration, then static ===========*/ + + char name[32]; /* id for this entry */ + + int isdncontroller; /* controller to use 0 ... n */ + int isdnchannel; /* channel to use */ + + int isdntxdelin; /* tx delay, incoming connections */ + int isdntxdelout; /* tx delay, outgoing connections */ + + int usrdevicename; /* userland device to use */ + int usrdeviceunit; /* userland unit to use */ + + int remote_numbers_count; /* number of remote numbers */ +#define MAXRNUMBERS 8 /* max remote numbers */ + + remote_number_t remote_numbers[MAXRNUMBERS]; /* remote numbers to dial */ + + int remote_numbers_handling; /* how to handle the remote dialing */ +#define RNH_NEXT 0 /* use next number after last successfull */ +#define RNH_LAST 1 /* use last successfull for next call */ +#define RNH_FIRST 2 /* always use first number for next call */ + + char local_phone_dialout[TELNO_MAX]; /* our number to tell remote*/ + char local_phone_incoming[TELNO_MAX]; /* answer calls for this local number */ + +#define MAX_INCOMING 8 + int incoming_numbers_count; /* number of incoming allowed numbers */ + incoming_number_t remote_phone_incoming[MAX_INCOMING]; /* answer calls from this remote machine */ + + int dialin_reaction; /* what to do with incoming calls */ +#define REACT_ACCEPT 0 +#define REACT_REJECT 1 +#define REACT_IGNORE 2 +#define REACT_ANSWER 3 +#define REACT_CALLBACK 4 + + int b1protocol; /* hdlc / raw */ + + int idle_time_in; /* max idle time incoming calls */ + int idle_time_out; /* max idle time outgoing calls */ + + int unitlength; /* length of a charging unit */ +#define UNITLENGTH_DEFAULT 60 /* last resort unit length */ + + int earlyhangup; /* time in seconds to hangup */ + /* before the next expected */ + /* charging unit */ +#define EARLYHANGUP_DEFAULT 5 + + int ratetype; /* type of rate */ +#define NO_RATE (NRATES+1) +#define INVALID_RATE (-1) + + int unitlengthsrc; /* where we get the unit length from */ +#define ULSRC_NONE 0 /* nowhere specified */ +#define ULSRC_CMDL 1 /* specified on commandline */ +#define ULSRC_CMDLMIN 5 /* minimum value from cmdl */ +#define ULSRC_CMDLMAX 3600 /* minimum value from cmdl */ +#define ULSRC_CONF 2 /* get it from config file */ +#define ULSRC_RATE 3 /* get it dynamic from ratesfile*/ +#define ULSRC_DYN 4 /* dynamic calculated from AOCD */ + + char *answerprog; /* program to use for answering */ + char *connectprog; /* program run after negotiation finished */ + char *disconnectprog; /* program run after shutdown is complete */ + + int callbackwait; /* time to wait before calling back */ +#define CALLBACKWAIT_MIN 1 + + int calledbackwait; /* time to wait for remote callback */ +#define CALLEDBACKWAIT_MIN 2 + + int dialretries; /* no. of dial tries */ +#define DIALRETRIES_DEF 1 + + int recoverytime; /* time between 2 dial tries */ +#define RECOVERYTIME_MIN 1 + + int dialrandincr; /* use random dial time incr */ + + int usedown; /* set interface down yes/no */ + int downtries; /* retries before i/f is set down */ +#define DOWN_TRIES_MIN 2 +#define DOWN_TRIES_MAX 20 + int downtime; /* time i/f is down */ +#define DOWN_TIME_MIN 10 /* 10 seconds */ +#define DOWN_TIME_MAX 3600 /* 1 hour */ + + int dialouttype; /* type of outgoing connection */ +#define DIALOUT_NORMAL 0 /* normal dialout behaviour */ +#define DIALOUT_CALLEDBACK 1 /* remote is expected to callback */ + + int alert; /* alert time in sec if nonzero */ +#define MINALERT 5 /* 5 secs min */ +#define MAXALERT (3*60) /* 3 minutes max */ + + int inout; /* in/out, in-only or out-only */ +#define DIR_INOUT 0 +#define DIR_INONLY 1 +#define DIR_OUTONLY 2 + +/*===========================================================================*/ +/*============ filled in after start, then dynamic ==========================*/ +/*===========================================================================*/ + + int cdid; /* cdid for call */ +#define CDID_RESERVED (-1) + + int isdncontrollerused; /* the one we are using */ + int isdnchannelused; /* the one we are using */ + + int fs_position; /* fullscreen position */ + + int state; /* state of connection */ +#define ST_IDLE 0 /* connection is idle / disconnected */ + + /* normal dial out to remote */ +#define ST_DIAL 1 /* dialing */ +#define ST_DIALRTMRCHD 2 /* wait for dial retry time reached */ +#define ST_DIALRETRY 3 /* last/first dialing failed, retry */ + + /* PCB: passive callback, i'm being called back */ +#define ST_PCB_DIAL 4 /* dialing, trigger a callback */ +#define ST_PCB_DIALFAIL 5 /* dialing failed triggering a callbk */ +#define ST_PCB_WAITCALL 6 /* waiting for callback from remote */ + + /* ACB: active callback, i'm calling back */ +#define ST_ACB_WAITDISC 7 /* got call, wait for disconnect */ +#define ST_ACB_WAITDIAL 8 /* wait until allowed to callback */ +#define ST_ACB_DIAL 9 /* callback to remote */ +#define ST_ACB_DIALFAIL 10 /* callback to remote failed */ + + /* normal non-dialling states */ +#define ST_ACCEPTED 11 /* remote accepted */ +#define ST_CONNECTED 12 /* connected with remote */ +#define ST_WAITDISCI 13 /* tx disc req, wait for disc ind */ +#define ST_DOWN 14 /* interface is down */ +#define ST_ALERT 15 /* interface is waiting for alert time*/ + + /* illegal and pseudo states */ +#define ST_ILL 16 /* illegal state */ +#define ST_SUSE 17 /* subroutine sets new state */ + +#define N_STATES (ST_ILL+1) /* max number of states */ + + int disc_cause; /* cause from disconnect */ + + int local_disconnect; /* flag, who disconnected */ +#define DISCON_LOC 0 +#define DISCON_REM 1 + + int timerval; /* value for timer, 0 if inactive */ + int timerremain; /* remaining time */ + + int hangup; /* flag, hangup connection asap */ + + char real_phone_incoming[TELNO_MAX]; /* real remote telno in case of wildcard */ + + int last_remote_number; /* index of last used dialout number*/ + + char remote_phone_dialout[TELNO_MAX]; /* used remote number to dial */ + + int direction; /* incoming or outgoing */ +#define DIR_IN 0 +#define DIR_OUT 1 + + int charge; /* charge in units */ + int last_charge; /* last charge in units */ + + int inbytes; /* # of bytes from remote */ + int iinbytes; /* # of bytes from remote on the line */ + int inbps; /* bytes/sec from remote */ + int outbytes; /* # of bytes to remote */ + int ioutbytes; /* # of bytes to remote on the line */ + int outbps; /* bytes/sec to remote */ + + time_t connect_time; /* time connection was established */ + + time_t aoc_last; /* last AOCD timestamp */ + time_t aoc_now; /* current AOCD timestamp */ + time_t aoc_diff; /* current unit length */ + time_t aoc_lastdiff; /* last charge unit length */ + int aoc_valid; /* flag: time diff is valid */ +#define AOC_INVALID 0 /* aoc_diff is NOT valid */ +#define AOC_VALID 1 /* aoc_diff is valid */ + + time_t last_dial_time; /* time of last dialing */ + time_t last_release_time; /* time of last hangup */ + + int dial_count; /* number of dialout tries */ + int randomtime; /* random() part of recoverytime*/ +#define RANDOM_MASK 0x04 /* bits used from randomtime */ + + int down_retry_count; /* retry cycle count for usedown*/ + time_t went_down_time; /* time i/f went down */ + phantom_t saved_call; /* outgoing call state if called + back too early */ + + int alert_time; /* count down of alert time */ + char display[DISPLAY_MAX]; +} cfg_entry_t; + +/*---------------------------------------------------------------------------* + * this struct describes state of controller with 2 b channels + *---------------------------------------------------------------------------*/ +typedef struct isdn_ctrl_state { + int ctrl_type; /* type: active/passive */ + int card_type; /* manufacturer (CARD_XXXX) */ + int state; /* controller state */ +#define CTRL_DOWN 0 /* controller inoparable */ +#define CTRL_UP 1 /* controller may be used */ + int stateb1; /* B-channel 1 */ + int stateb2; /* B-channel 2 */ +#define CHAN_IDLE 0 /* channel is free for usage */ +#define CHAN_RUN 1 /* channel is occupied */ + int freechans; /* number of unused channels */ +#define MAX_CHANCTRL 2 /* free channels per controller */ + int tei; /* tei or -1 if invalid */ +} isdn_ctrl_state_t; + +/*---------------------------------------------------------------------------* + * this struct describes a logging regular expression + *---------------------------------------------------------------------------*/ +struct rarr { + int re_flg; /* valid entry flag */ + char *re_expr; /* plain text expression */ + regex_t re; /* compiled expression */ + char *re_prog; /* the program to be executed */ +}; + +#ifdef I4B_EXTERNAL_MONITOR +/* for each rights entry we keep one of this structures around: */ +struct monitor_rights { + char name[FILENAME_MAX]; /* net/host spec or filename */ + int rights; /* bitmask of allowed acces rights */ + u_int32_t net; /* net/host address (host byte order!) */ + u_int32_t mask; /* bitmask 1 = network, 0 = host (host byte order!) */ + int local; /* zero if remote access via tcp/ip */ +}; +#endif + +/*---------------------------------------------------------------------------* + * global variables, storage allocation + *---------------------------------------------------------------------------*/ +#ifdef MAIN + +int isdnfd; /* file handle, /dev/i4b */ + +char *configfile = CONFIG_FILE_DEF; /* configuration filename */ +int config_error_flag = 0; /* error counter */ + +#ifdef DEBUG +int do_debug = 0; /* debug mode flag */ +int debug_flags = 0; /* debug options */ +int debug_noscreen = 0; /* not on fullscreen */ +#endif + +int do_bell = 0; /* bell on connect/disconnect */ + +int do_fork = 1; /* run as daemon/foreground */ + +int do_ttytype = 0; /* got new terminal type */ +char *ttype = ""; /* termcap entry name string */ + +int do_rdev = 0; /* redirect output */ +char *rdev = ""; /* new device string */ + +int do_print = 0; /* config file printout */ + +int got_unitlen = 0; /* flag, got length of a unit */ +time_t unit_length; /* length of a unit */ + +cfg_entry_t cfg_entry_tab[CFG_ENTRY_MAX]; /* configuration table */ +isdn_ctrl_state_t isdn_ctrl_tab[ISDN_CTRL_MAX]; /* controller states table */ + +int ncontroller = 0; /* # of controllers available */ +int nentries = 0; /* # of entries in config tab */ + +int uselogfile = 0; /* flag, use a logfile */ +char logfile[MAXPATHLEN] = LOG_FILE_DEF; /* log filename */ +FILE *logfp = NULL; /* log file pointer */ +int logfacility = LOG_LOCAL0; /* the syslog facility used */ +int nregex = 0; /* number of reg expr */ +struct rarr rarr[MAX_RE]; /* regexpr & progs table */ + +char ratesfile[MAXPATHLEN] = RATES_FILE_DEF; /* rates filename */ +char *rate_error = NULL; /* errorcase: error string */ +int got_rate = 0; /* flag, ratesfile found */ +struct rates *rates[NRATES][NDAYS]; /* the rates structure */ + +int useacctfile = 0; /* flag, write accounting */ +char acctfile[MAXPATHLEN] = ACCT_FILE_DEF; /* accounting filename */ +FILE *acctfp = NULL; /* accounting file pointer */ +int acct_all = 1; /* account all connections */ + +int aliasing = 0; /* enable alias processing */ +char aliasfile[MAXPATHLEN] = ALIASFILE; /* alias file location */ + +int do_fullscreen = 0; /* fullscreen log */ +int curses_ready = 0; /* curses initialized */ + +#ifdef USE_CURSES +WINDOW *upper_w; /* curses upper window pointer */ +WINDOW *mid_w; /* curses mid window pointer */ +WINDOW *lower_w; /* curses lower window pointer */ +#endif + +int rt_prio = RTPRIO_NOTUSED; /* realtime priority */ + +/* monitor via network */ + +int do_monitor = 0; +int inhibit_monitor = 0; +#ifdef I4B_EXTERNAL_MONITOR +int monitorport = DEF_MONPORT; +#else +int monitorport = -1; +#endif +int accepted = 0; + +int isdntime = 0; /* flag, log time from exchange */ + +#else /* !MAIN */ + +int isdnfd; + +char *configfile; +int config_error_flag; + +#ifdef DEBUG +int do_debug; +int debug_flags; +int debug_noscreen; +#endif + +int do_bell; + +int do_fork; + +int do_ttytype; +char *ttype; + +int do_rdev; +char *rdev; + +int do_print; + +int got_unitlen; +time_t unit_length; + +cfg_entry_t cfg_entry_tab[CFG_ENTRY_MAX]; /* configuration table */ +isdn_ctrl_state_t isdn_ctrl_tab[ISDN_CTRL_MAX]; /* controller states table */ + +int ncontroller; +int nentries; + +int uselogfile; +char logfile[MAXPATHLEN]; +int logfacility; +int nregex; +struct rarr rarr[MAX_RE]; + +char ratesfile[MAXPATHLEN]; +char *rate_error; +int got_rate; +struct rates *rates[NRATES][NDAYS]; + +int useacctfile; +char acctfile[MAXPATHLEN]; +FILE *acctfp; +int acct_all; + +int aliasing; +char aliasfile[MAXPATHLEN]; + +int do_fullscreen; +int curses_ready; + +#ifdef USE_CURSES +WINDOW *upper_w; +WINDOW *mid_w; +WINDOW *lower_w; +#endif + +int rt_prio; + +int do_monitor; +int inhibit_monitor; +int monitorport; +int accepted; + +int isdntime; + +#endif /* MAIN */ + +char * bdrivername ( int drivertype ); +void cfg_setval ( int keyword ); +void check_and_kill ( cfg_entry_t *cep ); +void check_pid ( void ); +void close_allactive ( void ); +void configure ( char *filename, int reread ); +void daemonize ( void ); +void dialresponse(cfg_entry_t *cep, int dstat); +void display_acct ( cfg_entry_t *cep ); +void display_bell ( void ); +void display_ccharge ( cfg_entry_t *cep, int units ); +void display_chans ( void ); +void display_charge ( cfg_entry_t *cep ); +void display_connect ( cfg_entry_t *cep ); +void display_disconnect ( cfg_entry_t *cep ); +void display_l12stat(int controller, int layer, int state); +void display_tei(int controller, int tei); +void display_updown ( cfg_entry_t *cep, int updown ); +void hangup_channel ( int channel ); +void do_exit ( int exitval ); +void do_menu ( void ); +int exec_answer ( cfg_entry_t *cep ); +int exec_connect_prog ( cfg_entry_t *cep, const char *prog, int link_down ); +pid_t exec_prog ( char *prog, char **arglist ); +cfg_entry_t * find_by_device_for_dialout ( int drivertype, int driverunit ); +cfg_entry_t * find_matching_entry_incoming ( msg_connect_ind_t *mp ); +cfg_entry_t * find_active_entry_by_driver ( int drivertype, int driverunit ); +void finish_log ( void ); +char * getlogdatetime ( void ); +int get_cdid ( void ); +cfg_entry_t * get_cep_by_cc ( int ctrlr, int chan ); +cfg_entry_t * get_cep_by_driver ( int drivertype, int driverunit ); +cfg_entry_t * get_cep_by_cdid ( int cdid ); +int get_current_rate ( cfg_entry_t *cep, int logit ); +void handle_charge ( cfg_entry_t *cep ); +void handle_recovery ( void ); +void if_up(cfg_entry_t *cep); +void if_down(cfg_entry_t *cep); +void init_controller ( void ); +void init_log ( void ); +void init_screen ( void ); +void log ( int what, const char *fmt, ... ); +int main ( int argc, char **argv ); +void msg_accounting ( msg_accounting_ind_t *mp ); +void msg_alert_ind ( msg_alert_ind_t *mp ); +void msg_charging_ind ( msg_charging_ind_t *mp ); +void msg_connect_active_ind ( msg_connect_active_ind_t *mp ); +void msg_connect_ind ( msg_connect_ind_t *mp ); +void msg_pdeact_ind(msg_pdeact_ind_t *md); +void msg_negcomplete_ind(msg_negcomplete_ind_t *ind); +void msg_ifstatechg_ind(msg_ifstatechg_ind_t *ind); +void msg_drvrdisc_req(msg_drvrdisc_req_t *mp); +void msg_dialout ( msg_dialout_ind_t *mp ); +void msg_disconnect_ind ( msg_disconnect_ind_t *mp ); +void msg_idle_timeout_ind ( msg_idle_timeout_ind_t *mp ); +void msg_l12stat_ind(msg_l12stat_ind_t *ml); +void msg_teiasg_ind(msg_teiasg_ind_t *mt); +void msg_proceeding_ind ( msg_proceeding_ind_t *mp ); +const char * name_of_controller(int ctrl_type, int card_type); +void next_state ( cfg_entry_t *cep, int event ); +char * print_i4b_cause( cause_t code ); +char * printstate ( cfg_entry_t *cep ); +int readrates ( char *filename ); +int ret_channel_state(int controller, int channel); +void reopenfiles ( int dummy ); +void rereadconfig ( int dummy ); +void select_first_dialno ( cfg_entry_t *cep ); +void select_next_dialno ( cfg_entry_t *cep ); +void select_this_dialno ( cfg_entry_t *cep ); +int sendm_alert_req ( cfg_entry_t *cep ); +int sendm_connect_req ( cfg_entry_t *cep ); +int sendm_connect_resp ( cfg_entry_t *cep, int cdid, int response, int cause ); +int sendm_disconnect_req ( cfg_entry_t *cep, int cause ); +int set_channel_busy(int controller, int channel); +int set_channel_idle(int controller, int channel); +int setup_dialout(cfg_entry_t *cep); +void sigchild_handler ( int sig ); +void start_timer ( cfg_entry_t *cep, int seconds ); +void stop_timer ( cfg_entry_t *cep ); +void unitlen_chkupd( cfg_entry_t *cep ); +void write_pid ( void ); +void yyerror ( const char *msg ); + +/* montior server module */ +void monitor_init(); +void monitor_exit(); +void monitor_clear_rights(); +void monitor_fixup_rights(); +int monitor_start_rights(const char *clientspec); +void monitor_add_rights(int rights); + +/* possible return codes from monitor_start_rights: */ +#define I4BMAR_OK 0 /* rights added successfully */ +#define I4BMAR_LENGTH 1 /* local socket name to long */ +#define I4BMAR_DUP 2 /* entry already exists */ +#define I4BMAR_CIDR 3 /* cidr netmask is invalid */ +#define I4BMAR_NOIP 4 /* host/net could not be resolved */ + +int monitor_create_local_socket(); + +#ifndef I4B_NOTCPIP_MONITOR +int monitor_create_remote_socket(int portno); +#endif + +void monitor_prepselect(fd_set *selset, int *max_fd); +void monitor_handle_input(fd_set *selset); +void monitor_handle_connect(int sockfd, int is_local); +void monitor_evnt_charge(cfg_entry_t *cep, int units, int estimated); +void monitor_evnt_connect(cfg_entry_t *cep); +void monitor_evnt_disconnect(cfg_entry_t *cep); +void monitor_evnt_updown(cfg_entry_t *cep, int up); +void monitor_evnt_log(int prio, const char * what, const char * msg); + +/* controller.c */ + +int init_controller_state(int controller, int ctrl_type, int card_type, int tei); +int set_controller_state(int controller, int state); +int get_controller_state(int controller); +int decr_free_channels(int controller); +int incr_free_channels(int controller); +int get_free_channels(int controller); +int set_channel_busy(int controller, int channel); +int set_channel_idle(int controller, int channel); +int ret_channel_state(int controller, int channel); + +/* alias.c */ + +void init_alias(char *filename); +void free_aliases(void); +char *get_alias(char *number); + +#endif /* _ISDND_H_ */ diff --git a/usr.sbin/i4b/isdnd/isdnd.rates.5 b/usr.sbin/i4b/isdnd/isdnd.rates.5 new file mode 100644 index 0000000..450cd5e --- /dev/null +++ b/usr.sbin/i4b/isdnd/isdnd.rates.5 @@ -0,0 +1,115 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdnd.rates.5,v 1.6 1998/12/05 18:03:21 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:09:57 1998] +.\" +.Dd September 11, 1998 +.Dt isdnd.rates 5 +.Sh NAME +.Nm isdnd.rates +.Nd isdn4bsd ISDN management daemon rates description file +.Sh DESCRIPTION +The file +.Pa isdnd.rates +contains descriptions how long charging units last at a given time of day, +day of week and the distance to the destination. If this file is available, +this information may be used by the +.Xr isdnd 8 +ISDN connection management daemon to calculate the short hold time for a +connection. +.Pp +The format of a rate entry line is a follows: +.Pp +The first field, the +.Pq Fa rate-code +defines a collection of rates (for each day of the week) which can be +referenced in the +.Xr isdnd 8 +configuration file +.Xr isdnd.rc 5 . +This field must start with the identifier +.Dq ra +followed by a digit in the range of zero to four. +.Pp + +The second field, the +.Pq Fa day-number +selects the day of week for which this entry defines the rates, where 0 stands +for Sunday, 1 for Monday and so on until the digit 6 which stands for Saturday. +.Pp + +The rest of the line consists of one or more space separated fields which have +the following syntax: +.Bd -filled -offset indent +start_hour.start_minutes-end_hour.end_minutes:charge_unit_length +.Ed +.Pp +Start_hour and start_minutes define the begin of a time section and end_hour +and end_minutes define the end. Charge_unit_length define the length of a +charging unit in the previously defined time section. No spaces or tabs are +allowed inside this field. The hour and minutes specifications MUST have +exactly 2 digits, in case just one digit is needed, a leading 0 must be used. +.Pp +For example, +.Bd -filled -offset indent +14.00-18.00:90 +.Ed +.Pp +defines, that between 2:00 PM and 6:00 PM the length of one charging unit +lasts 90 seconds. +.Pp + +.Sh FILES +.Bl -tag -width /etc/isdn/isdnd.rates -compact +.It Pa /etc/isdn/isdnd.rates +The default rates specification file for the +.Nm isdnd +ISDN daemon. + +.Sh EXAMPLES +The line: +.Bd -literal +ra0 0 00.00-05.00:240 05.00-21.00:150 21.00-24.00:240 +.Ed +.Pp +defines the unit lengths for a Sunday. + +.Sh SEE ALSO +.Xr isdnd 8 , +.Xr isdnd.rc 5 + +.Sh AUTHOR +The rates subsystem for the +.Xr isdnd 8 +daemon to which +.Nm +belongs was designed and written by Gary Jennejohn. +.Pp +The +.Xr isdnd 8 +daemon and this manual page were written by Hellmuth Michaelis. +He can be reached at hm@kts.org or hm@hcs.de. + diff --git a/usr.sbin/i4b/isdnd/isdnd.rc.5 b/usr.sbin/i4b/isdnd/isdnd.rc.5 new file mode 100644 index 0000000..03d1a3a --- /dev/null +++ b/usr.sbin/i4b/isdnd/isdnd.rc.5 @@ -0,0 +1,642 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdnd.rc.5,v 1.27 1998/12/05 18:03:23 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:10:08 1998] +.\" +.Dd October 27, 1998 +.Dt isdnd.rc 5 +.Sh NAME +.Nm isdnd.rc +.Nd isdn4bsd ISDN connection management daemon config file format +.Sh DESCRIPTION +The file +.Pa /etc/isdn/isdnd.rc +contains (if not otherwise specified on the command line) the runtime +configuration for the +.Xr isdnd 8 +ISDN connection management daemon which is part of the isdn4bsd package. +.Pp +The configuration file consists of keywords which start in column 1 followed by +one or more spaces or tabs, an equal sign, one or more spaces or tabs +and a keyword dependent parameter value. +.Pp +A line beginning with '#' is treated as a comment line. +.Pp +For keywords requiring the specification of a boolean value, the truth +value can be either +.Em yes +or +.Em on +while the false value can be either +.Em no +or +.Em off . +.Pp +The configuration file consists of one +.Em system +section and one or more +.Em entry +sections. +In the +.Em system +section parameters regarding the daemon operation or parameters +not associated with a single remote connection can be set. +In the +.Em entry +section(s) parameters directly associated with a single remote +connection can be set. +.Pp +The following keywords are recognized by +.Nm isdnd : +.Pp +.Bl -tag -width system -compact + +.It Li system +This keyword starts the system configuration section. It must not +have a parameter and may be used only once. The keyword is mandatory. +The following keywords are valid in the system configuration section: +.Bl -tag -width useacctfile -compact + +.It Li acctall +If this parameter is set to +.Em on , +accounting information is written even if the local site was not charged +or no charging information is available or is not subscribed. (optional) + +.It Li acctfile +Specifies the name of the accounting file which is used when the keyword +.Em useacctfile +(see below) is set to +.Em on . +If this keyword is omitted the system default is used. (optional) + +.It Li aliasing +If this parameter is set to +.Em on , +alias processing of telephone-number to name is enabled (see also the +.Em aliasfile +keyword below). The default is off. (optional) + +.It Li aliasfile +Specifies the name of the telephone number-to-name alias database file shared +with the +.Xr isdntel 1 +utility when alias processing is enabled via the +.Em aliasing +keyword. (optional) + +.It Li isdntime +If this parameter is set to +.Em on , +date/time information from the exchange (if provided) is written to the +logfile. The default is off. (optional) + +.It Li monitor-allowed +If this parameter is set to +.Em on +or +.Em yes , +monitoring via a local or remote machine is enabled. +This parameter is optional and is set to +.Em off +by default. + +.It Li monitor-port +sets the TCP port number for remote monitoring. +This integer parameter is optional and is set to port 451 by default. + +.It Li monitor +This keyword specifies a local socket name or a host or network for remote +monitoring. The +.Em monitor +specification may either be: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar the name of a local (UNIX-domain) socket +this MUST start with a "/", example: /var/run/isdn-monitor +.It Ar a dotted-quad host specification +example: 192.168.1.2 +.It Ar a dotted-quad network address with netmask +example: 192.168.1.0/24 +.It Ar a resolvable host name +example: localhost +.It Ar a resolvable network name with netmask +example: up-vision-net/24 +.El + +.It Li monitor-access +This keyword specifies the access rights for a previously used +.Em monitor +keyword. The supported access rights are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar fullcmd +.It Ar restrictedcmd +.It Ar channelstate +.It Ar logevents +.It Ar callin +.It Ar callout +.El + +.It Li ratesfile +Specifies the name of the ratesfile. If this keyword is omitted the system +default is used. (optional) + +.It Li regexpr +This keyword is used to specify regular expressions. It can be specified +more than once up to a compile time dependent value (currently set to 5 by +the MAX_RE definition in the source). +.Pp +All specified regular expressions are compared to the log strings at runtime +and if a match is found, a program is run with the log text as a parameter +(see also the keyword +.Em regprog +below). +.Pp +For an explanation how regular expressions are specified, please have a +look at +.Xr re_format 7 +and +.Xr regex 3 . +The +.Em extended +regular expression syntax is supported here. +.Pp +Hint: it might be necessary to properly quote the expression to avoid +improper interpretation by the configuration file parser. +(optional) + +.It Li regprog +This keyword is used to specify the name of a program which is run in +case a corresponding regular expression is matched by a logging string. +.Nm Isdnd +expects to find the program below the path +.Pa /etc/isdn +which is prepended to the string specified as a parameter to this keyword. +(optional) + +.It Li rtprio +Specifies the realtime priority +.Nm isdnd +runs at as an integer value in the range 0...31 with 0 being the highest +priority. This keyword is optional; if not specified the process priority of +.Nm isdnd +is not touched in any way. +( See also +.Xr rtprio 1 +). +This keyword is only available if +.Nm +was compiled with -DUSE_RTPRIO. + +.It Li useacctfile +If this parameter is set to +.Em on +charging (if available) and accounting information is written to the +accounting file. (optional) + +.El + +.It Li entry +This keyword starts one configuration entry. It must not have a parameter. +This keyword must be used at least once. +The following keywords are valid in an entry section: +.Bl -tag -width unitlengthsrc -compact + +.It Li answerprog +This keyword is used to specify the name of a program which is run in +case an incoming telephone connection specified +.Em answer +in its configuration entry. The default name is +.Em answer . +.Nm Isdnd +expects to find this program beneath the path +.Pa /etc/isdn +which is prepended to the string specified as a parameter to this keyword. +(optional) + +.It Li alert +is used to specify a time in seconds to wait before accepting a call. This +keyword is only usable for incoming telephone calls (dialin-reaction = answer). +It is used to have a chance to accept an incoming call on the phone before +the answering machine starts to run. The minimum value for the alert parameter +is 5 seconds and the maximum parameter allowed is 180 seconds. +(optional) + +.It Li b1protocol +The B channel layer 1 protocol used for this connection. The keyword is mandatory. +The currently configurable values are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar hdlc +HDLC framing. +.It Ar raw +No framing at all (used for telephony). +.El + +.It Li callbackwait +The time in seconds to wait between hanging up the call from a remote site +and calling back the remote site. (optional) + +.It Li calledbackwait +The time in seconds to wait for a remote site calling back the local site +after a call from the local site to the remote site has been made. (optional) + +.It Li dialin-reaction +Used to specify what to do when an incoming connection request is received. +The keyword is mandatory. +The currently supported parameters are: +.Pp +.Bl -tag -width calledback -compact -offset +.It Ar accept +Accept an incoming call. +.It Ar reject +Reject an incoming call. +.It Ar ignore +Ignore an incoming call. +.It Ar answer +Start telephone answering for an incoming voice call. +.It Ar callback +When a remote site calls, hangup and call back the remote site. +.El + +.It Li dialout-type +This keyword ist used to configure what type of dialout mode is used. +The keyword is mandatory. +The currently supported parameters are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar normal +Normal behavior, call the remote site which is supposed to accept the call. +.It Ar calledback +Callback behavior, call the remote side which rejects the call and calls +us back. +.El + +.It Li dialrandincr +When dialing or re-dialing and this parameter is set to +.Em on , +the dial retry time is added with a random value (currently 0...3 seconds) +to minimize the chance of two sites dialing synchronously so each gets a busy +each time it dials because the other side is also dialing. + +.It Li dialretries +The number of dialing retries before giving up. (optional) + +.It Li direction +This keyword is used to configure if incoming and outgoing, incoming-only or +outgoing only connections are possible. +The keyword is optional, the default is +.Em inout . +.Pp +The currently supported parameters are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar inout +Normal behavior, connection establishment is possible from remote and local. +.It Ar in +Only incoming connections are possible. +.It Ar out +Only outgoing connections are possible. +.El + +.It Li downtries +is used to configure the number of unsuccessful tries (= retry cycles!) before +the interface is disabled (for +.Em downtime +seconds). +(see also the keyword +.Em usedown +further up). This keyword is optional. + +.It Li downtime +is used to configure the time in seconds an interface is disabled +after the configured number of +.Em downtries . +(see also the keyword +.Em usedown +further up). +This keyword is optional and is set to 60 seconds by default. + +.It Li earlyhangup +A (safety) time in seconds which specifies the time to hangup before an +expected next charging unit will occur. (optional) + +.It Li idletime-outgoing +The time in seconds an outgoing connection must be idle before hanging up. +(optional) + +.It Li idletime-incoming +The time in seconds an incoming connection must be idle before hanging up. +(optional) + +.It Li isdncontroller +The ISDN controller number to be used for connections for this entry. +(mandatory) + +.It Li isdnchannel +The ISDN controller channel number to be used for connections for this entry. +In case a channel is explicitly selected here, the SETUP message will request +this channel but mark the request as +.Em preferred +(the indicated channel is preferred) instead of exclusive (only the indicated +channel is acceptable). Thus the exchange is still free to select another +than the requested channel! +(mandatory) + +.It Li isdntxdel-incoming +A delay value suitable for the +.Em timeout() +kernel subroutine to delay the transmittion of the first packet after a +successfull connection is made by this value for +.Em incoming +ISDN connections. The specification unit is 1/100 second. A zero (0) disables +this feature and is the default value. This feature is implemented (and makes +sense only) for the +.Xr i4bipr 4 +IP over raw HDLC ISDN driver. (optional) + +.It Li isdntxdel-outgoing +A delay value suitable for the +.Em timeout() +kernel subroutine to delay the transmittion of the first packet after a +successfull connection is made by this value for +.Em outgoing +ISDN connections. The specification unit is 1/100 second. A zero (0) disables +this feature and is the default value. This feature is implemented (and makes +sense only) for the +.Xr i4bipr 4 +IP over raw HDLC ISDN driver. (optional) + +.It Li local-phone-dialout +The local telephone number used when the local site dials out. When dialing +out to a remote site, the number specified here is put into the +.Em "Calling Party Number Information Element" . +.Pp +This keyword is mandatory for the +.em +ipr +userland interfaces. + +.It Li local-phone-incoming +The local telephone number used for verifying the destination of incoming +calls. When a remote site dials in, this number is used to verify that it +is the local site which the remote site wants to connect to. It is compared +with the +.Em "Called Party Number Information Element" +got from the telephone exchange. +.Pp +This keyword is mandatory for the ipr interfaces. + +.It Li name +Defines a symbolic name for this configuration entry. It's purpose is to +use this name in the full-screen display for easy identification of a link +to a remote site and for accounting purposes. (mandatory) + +.It Li ratetype +The rate entry used from the rates file. (optional) +.br +For example, ratetype=0 selects lines beginning "ra0" in /etc/isdn/isdnd.rates; +(typically ra0 lines are a set of tables for local call rates on different +days of the week & times per day). + +.It Li recoverytime +The time in seconds to wait between dial retries. (optional) + +.It Li remdial-handling +is used to specify the dialout behavior in case more than one outgoing +number is specified. +The currently supported parameters are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar first +For every new (non-retry) call setup, start with the first number. +.It Ar last +For every new (non-retry) call setup, start with the last number with +which a successful connection was made. +.It Ar next +For every new (non-retry) call setup, start with the next number which +follows the last one used. +.El + +.It Li remote-phone-dialout +The remote telephone number used when the local site dials out. When dialing +out to a remote site, the number specified here is put into the +.Em "Called Party Number Information Element" . +.Pp +This keyword is mandatory for the +.em +ipr +interfaces. It may be specified more than once to try to dial to several +numbers until one succeeds. + +.It Li remote-phone-incoming +The remote telephone number used to verify an incoming call. When a remote site +dials in, this number is used to verify that it is the correct remote site +which is herewith authorized to connect into the local system. This parameter +is compared against the +.Em "Calling Party Number Information Element" +got from the telephone exchange. +.Pp +This keyword is mandatory for the ipr interfaces. +.Pp +This keyword may have a wildcard parameter '*' to permit anyone dialing in. + +.It Li unitlength +The length of a charging unit in seconds. This is used in conjunction with +the idletime to decide when to hangup a connection. (optional) + +.It Li unitlengthsrc +This keyword is used to specify from which source +.Xr isdnd 8 +takes the unitlength for shorthold mode. The currently configurable values are: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar none +Then unitlength is not specified anywhere. +.It Ar cmdl +Use the unitlength specified on the commandline. +.It Ar conf +Use the unitlength specified in the configuration file with the keyword +.Em unitlength . +.It Ar rate +Use the unitlength from the ratesfile specified in the configuration +file with the keyword +.Em ratetype . +.It Ar aocd +Use a dynamically calculated unitlength in case AOCD is subscribed on +the ISDN line. (AOCD is an acronym for ``Advice Of Charge During the call'' +which is a service provided by the telecommunications (ie phone) provider, +to indicate billable units). +.El + +.It Li usrdevicename +Specifies the userland interface which is used for interfacing ISDN B channel +data to the userland. The keyword is mandatory. +This keyword accepts the following parameters: +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar ipr +This parameter configures a raw HDLC IP over ISDN interface. +.It Ar isp +This parameter configures a synchronous PPP over ISDN interface. +.It Ar rbch +This specifies a Raw B CHannel access interface. +.It Ar tel +ISDN telephony. +.El + +.It Li usrdeviceunit +Specifies the unit number for the with the +.em +usrdevicename +specified device. + +.It Li usedown +is used to enable the use of the keywords +.Em downtries +and +.Em downtime +in the entries section(s). It is used in the +.Nm isdnd +daemon to dynamically enable and disable the IP interfaces to avoid excessive +dialing activities in case of transient failures (such as busy lines). +This parameter is optional and is set to +.Em off +by default. + +.It Li connectprog +specifies a program run everytime after a connection is established and +address negotiation is complete (i.e.: the connection is useable). +.Nm Isdnd +expects to find the program below the path +.Pa /etc/isdn +which is prepended to the string specified as a parameter to this keyword. +(optional) + +.It Li disconnectprog +specifies a program run everytime after a connection was shut down. +.Nm Isdnd +expects to find the program below the path +.Pa /etc/isdn +which is prepended to the string specified as a parameter to this keyword. +(optional) + +.El +.El + +.Sh IDLETIME CALCULATION AND SHORTHOLD MODE +.Bl -tag -width incoming calls -compact +.It Li incoming calls +It is assumed that the calling side knows most about charging structures and +such and as a consequence only the keyword +.Em idletime-incoming +has a function for incoming calls. +.Pp +For incoming calls the line is constantly monitored, and in case there was +not traffic taking place for the time in seconds specified by +.Em idletime-incoming +the call is closed. +.Pp +Typically, +.Em idletime-incoming +is used as a last resort and is therefore set much higher than a charging +unit time: typical values are one to five minutes. + +.It Li outgoing calls +Outgoing call disconnect time can be setup in one of two ways: + +.Bl -tag -width shorthold mode -compact +.It Li simple mode +For simple mode, the selected +.Em unitlength +must be 0 (zero) and +.Em idletime-outgoing +greater zero. +.Pp +The outgoing traffic is constantly monitored, and in case there was +not traffic taking place for the time in seconds specified by +.Em idletime-outgoing +the call is closed. +.Pp +Typical values in simple mode are 10 to 30 seconds. + +.It Li shorthold mode +For shorthold mode, the selected +.Em unitlength +and +.Em idletime-outgoing +must be greater than 0 (zero); +.Em earlyhangup must be >= 0 (zero). + +.Bd -literal + +|<unchecked-window>|<checkwindow>|<safetywindow>| +| | | | ++------------------+-------------+--------------+ +| | | | +| |<-idle-time->|<earlyhangup->| +|<--------------unitlength--------------------->| + +.Ed + +During the unchecked window which is (unitlength - (idle-time+earlyhangup)) +in length, no idle check is done. After the unchecked window has ended, +the line is checked for idle-time length if no traffic takes place. In case +there was traffic detected in the check-window, the same procedure is restarted +at the beginning of the next unit. In case no traffic was detected during +the check-window, the line is closed at the end of the check window. +.Pp +Notice: +.Em unitlength +must (!) be greater than the sum of +.Em idletime-outgoing +and +.Em earlyhangup ! + +.El +.El + +.Pp + +.Sh FILES +.Bl -tag -width /etc/isdn/isdnd.rc -compact +.It Pa /etc/isdn/isdnd.rc +The default configuration file for the +.Nm isdnd +ISDN daemon. + +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnmonitor 8 +.Xr regex 3 +.Xr re_format 7 + +.Sh AUTHOR +The +.Xr isdnd 8 +daemon and this manual page were written by Hellmuth Michaelis. +He can be reached at hm@kts.org. diff --git a/usr.sbin/i4b/isdnd/log.c b/usr.sbin/i4b/isdnd/log.c new file mode 100644 index 0000000..4c1ffb6 --- /dev/null +++ b/usr.sbin/i4b/isdnd/log.c @@ -0,0 +1,242 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - logging routines + * ----------------------------- + * + * $Id: log.c,v 1.14 1998/12/05 18:03:24 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:10:22 1998] + * + *---------------------------------------------------------------------------*/ + +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <time.h> +#include <errno.h> +#include <syslog.h> +#include <unistd.h> +#include <regex.h> + +#include <machine/i4b_ioctl.h> + +#include "isdnd.h" + +#define LOGBUFLEN 256 + +extern int do_monitor; +extern int accepted; +extern FILE *logfp; + +static void check_reg(char *logstring); + +struct logtab { + char *text; + int pri; +}; + +/*---------------------------------------------------------------------------* + * table for converting internal log levels into syslog levels + *---------------------------------------------------------------------------*/ +static struct logtab logtab[] = { + {"ERR", LOG_ERR}, /* error conditions */ + {"WRN", LOG_WARNING}, /* warning conditions, nonfatal */ + {"DMN", LOG_NOTICE}, /* normal but significant condition, daemon*/ + {"CHD", LOG_INFO}, /* informational, call handling */ + {"DBG", LOG_DEBUG} /* debug messages */ +}; + +/*---------------------------------------------------------------------------* + * initialize logging + *---------------------------------------------------------------------------*/ +void +init_log(void) +{ + int i; + + if(uselogfile) + { + if((logfp = fopen(logfile, "a")) == NULL) + { + fprintf(stderr, "ERROR, cannot open logfile %s: %s\n", + logfile, strerror(errno)); + exit(1); + } + + /* set unbuffered operation */ + + setvbuf(logfp, (char *)NULL, _IONBF, 0); + } + else + { +#if DEBUG + if(do_debug && do_fork == 0 && do_fullscreen == 0) + (void)openlog("isdnd", + LOG_PID|LOG_CONS|LOG_NDELAY|LOG_PERROR, + logfacility); + else +#endif + (void)openlog("isdnd", LOG_PID|LOG_CONS|LOG_NDELAY, + logfacility); + } + + /* initialize the regexp array */ + + for(i = 0; i < MAX_RE; i++) + { + char *p; + char buf[64]; + + sprintf(buf, "%s%d", REGPROG_DEF, i); + + rarr[i].re_flg = 0; + + if((p = malloc(strlen(buf) + 1)) == NULL) + { + log(LL_DBG, "init_log: malloc failed: %s", strerror(errno)); + do_exit(1); + } + + strcpy(p, buf); + + rarr[i].re_prog = p; + } +} + +/*---------------------------------------------------------------------------* + * finish logging + *---------------------------------------------------------------------------*/ +void +finish_log(void) +{ + if(uselogfile) + { + fflush(logfp); + fclose(logfp); + } + else + { + (void)closelog(); + } +} + +/*---------------------------------------------------------------------------* + * place entry into logfile + *---------------------------------------------------------------------------*/ +void +log(int what, const char *fmt, ...) +{ + char buffer[LOGBUFLEN]; + register char *dp; + va_list ap; + + va_start(ap, fmt); + vsnprintf(buffer, LOGBUFLEN-1, fmt, ap); + va_end(ap); + + dp = getlogdatetime(); /* get time string ptr */ + +#ifdef USE_CURSES + + /* put log on screen ? */ + + if((do_fullscreen && curses_ready) && + ((!debug_noscreen) || (debug_noscreen && (what != LL_DBG)))) + { + wprintw(lower_w, "%s %s %-.*s\n", dp, logtab[what].text, + COLS-((strlen(dp))+(strlen(logtab[what].text))+2), buffer); + wrefresh(lower_w); + } +#endif + +#ifdef I4B_EXTERNAL_MONITOR + monitor_evnt_log(logtab[what].pri, logtab[what].text, buffer); +#endif + + if(uselogfile) + { + fprintf(logfp, "%s %s %s\n", dp, logtab[what].text, buffer); + } + else + { + register char *s = buffer; + + /* strip leading spaces from syslog output */ + + while(*s && (*s == ' ')) + s++; + + syslog(logtab[what].pri, "%s %s", logtab[what].text, s); + } + + +#if DEBUG + if(what != LL_DBG) /* don't check debug logs, endless loop !!! */ +#endif + check_reg(buffer); +} + +/*---------------------------------------------------------------------------* + * return ptr to static area containing date/time + *---------------------------------------------------------------------------*/ +char * +getlogdatetime() +{ + static char logdatetime[41]; + time_t tim; + register struct tm *tp; + + tim = time(NULL); + tp = localtime(&tim); + strftime(logdatetime,40,I4B_TIME_FORMAT,tp); + return(logdatetime); +} + +/*---------------------------------------------------------------------------* + * check for a match in the regexp array + *---------------------------------------------------------------------------*/ +static void +check_reg(char *logstring) +{ + register int i; + + for(i = 0; i < MAX_RE; i++) + { + if(rarr[i].re_flg && (!regexec(&(rarr[i].re), logstring, (size_t) 0, NULL, 0))) + { + char* argv[3]; + argv[0] = rarr[i].re_prog; + argv[1] = logstring; + argv[2] = NULL; + + exec_prog(rarr[i].re_prog, argv); + break; + } + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/main.c b/usr.sbin/i4b/isdnd/main.c new file mode 100644 index 0000000..9d16717 --- /dev/null +++ b/usr.sbin/i4b/isdnd/main.c @@ -0,0 +1,707 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - main program entry + * ------------------------------- + * + * $Id: main.c,v 1.29 1998/12/05 18:03:26 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:10:38 1998] + * + *---------------------------------------------------------------------------*/ + +#ifdef I4B_EXTERNAL_MONITOR +#include "monitor.h" +#endif + +#define MAIN +#include "isdnd.h" +#undef MAIN + +#ifdef I4B_EXTERNAL_MONITOR + +#ifdef I4B_NOTCPIP_MONITOR +/* monitor via local socket */ +static void mloop(int sockfd); +#else /* I4B_NOTCPIP_MONITOR */ +/* monitor via local and tcp/ip socket */ +static void mloop(int localsock, int remotesock); +#endif /* I4B_NOTCPIP_MONITOR */ + +#else /* I4B_EXTERNAL_MONITOR */ +/* no monitoring at all */ +static void mloop(); +#endif /* I4B_EXTERNAL_MONITOR */ + +#ifdef USE_CURSES +static void kbdrdhdl(void); +#endif + +static void isdnrdhdl(void); +static void usage(void); + +#define MSG_BUF_SIZ 1024 /* message buffer size */ + +/*---------------------------------------------------------------------------* + * usage display and exit + *---------------------------------------------------------------------------*/ +static void +usage(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, "isdnd - i4b ISDN manager daemon, version %02d.%02d.%d, %s %s\n", VERSION, REL, STEP, __DATE__, __TIME__); +#ifdef DEBUG + fprintf(stderr, " usage: isdnd [-b] [-c file] [-d level] [-F]\n"); +#else + fprintf(stderr, " usage: isdnd [-b] [-c file] [-F]\n"); +#endif + fprintf(stderr, " [-f [-r dev] [-t termtype]] [-u time]\n"); + fprintf(stderr, " [-l] [-L file] [-s facility] [-m]\n"); + fprintf(stderr, " -b audible bell in fullscreen mode at connect/disconnect\n"); + fprintf(stderr, " -c <filename> configuration file name (def: %s)\n", CONFIG_FILE_DEF); +#ifdef DEBUG + fprintf(stderr, " -d <level> set debug flag bits:\n"); + fprintf(stderr, " general = 0x%04x, rates = 0x%04x, timing = 0x%04x\n", DL_MSG, DL_RATES, DL_TIME); + fprintf(stderr, " state = 0x%04x, retry = 0x%04x, dial = 0x%04x\n", DL_STATE, DL_RCVRY, DL_DIAL); + fprintf(stderr, " process = 0x%04x, kernio = 0x%04x ctrlstat = 0x%04x\n", DL_PROC, DL_DRVR, DL_CNST); + fprintf(stderr, " -dn no debug output on fullscreen display\n"); +#endif + fprintf(stderr, " -f fullscreen status display\n"); + fprintf(stderr, " -F do not become a daemon process\n"); + fprintf(stderr, " -l use a logfile instead of syslog\n"); + fprintf(stderr, " -L <file> use file instead of %s for logging\n", LOG_FILE_DEF); + fprintf(stderr, " -P pretty print real config to stdout and exit\n"); + fprintf(stderr, " -r <device> redirect output to other device (for -f)\n"); + fprintf(stderr, " -s <facility> use facility instead of %d for syslog logging\n", LOG_LOCAL0 >> 3); + fprintf(stderr, " -t <termtype> terminal type of redirected screen (for -f)\n"); + fprintf(stderr, " -u <time> length of a charging unit in seconds\n"); + fprintf(stderr, " -m inhibit network/local monitoring\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/*---------------------------------------------------------------------------* + * program entry + *---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int i; + msg_vr_req_t mvr; + +#ifdef I4B_EXTERNAL_MONITOR + int sockfd = -1; /* local monitor socket */ +#ifndef I4B_NOTCPIP_MONITOR + int remotesockfd = -1; /* tcp/ip monitor socket */ +#endif +#endif + + while ((i = getopt(argc, argv, "bmc:d:fFlL:Pr:s:t:u:?")) != EOF) + { + switch (i) + { + case 'b': + do_bell = 1; + break; + + case 'm': + inhibit_monitor = 1; + break; + + case 'c': + configfile = optarg; + break; + +#ifdef DEBUG + case 'd': + if(*optarg == 'n') + debug_noscreen = 1; + else if((sscanf(optarg, "%i", &debug_flags)) == 1) + do_debug = 1; + else + usage(); + break; +#endif + + case 'f': + do_fullscreen = 1; + do_fork = 0; +#ifndef USE_CURSES + fprintf(stderr, "Sorry, no fullscreen mode available - daemon compiled without USE_CURSES\n"); + exit(1); +#endif + break; + + case 'F': + do_fork = 0; + break; + + case 'l': + uselogfile = 1; + break; + + case 'L': + strcpy(logfile, optarg); + break; + + case 'P': + do_print = 1; + break; + + case 'r': + rdev = optarg; + do_rdev = 1; + break; + + case 's': + if(isdigit(*optarg)) + { + int facility; + logfacility = strtoul(optarg, NULL, 10); + facility = logfacility << 3; + + if((facility < LOG_KERN) || + (facility > LOG_FTP && facility < LOG_LOCAL0) || + (facility > LOG_LOCAL7)) + { + fprintf(stderr, "Error, option -s has invalid logging facility %d", logfacility); + usage(); + } + logfacility = facility; + } + else + { + fprintf(stderr, "Error: option -s requires a numeric argument!\n"); + usage(); + } + break; + + case 't': + ttype = optarg; + do_ttytype = 1; + break; + + case 'u': + if(isdigit(*optarg)) + { + unit_length = strtoul(optarg, NULL, 10); + if(unit_length < ULSRC_CMDLMIN) + unit_length = ULSRC_CMDLMIN; + else if(unit_length > ULSRC_CMDLMAX) + unit_length = ULSRC_CMDLMAX; + got_unitlen = 1; + } + else + { + fprintf(stderr, "Error: option -T requires a numeric argument!\n"); + usage(); + } + break; + + case '?': + default: + usage(); + break; + } + } +#ifdef DEBUG + if(!do_debug) + debug_noscreen = 0; +#endif + + if(!do_print) + { + umask(UMASK); /* set our umask ... */ + + init_log(); /* initialize the logging subsystem */ + } + + check_pid(); /* check if we are already running */ + + if(!do_print) + { + if(do_fork || (do_fullscreen && do_rdev)) /* daemon mode ? */ + daemonize(); + + write_pid(); /* write our pid to file */ + + /* set signal handler(s) */ + + signal(SIGCHLD, sigchild_handler); /* process handling */ + signal(SIGHUP, rereadconfig); /* reread configuration */ + signal(SIGUSR1, reopenfiles); /* reopen acct/log files*/ + signal(SIGPIPE, SIG_IGN); /* handled manually */ + signal(SIGINT, do_exit); /* clean up on SIGINT */ + signal(SIGTERM, do_exit); /* clean up on SIGTERM */ + signal(SIGQUIT, do_exit); /* clean up on SIGQUIT */ + } + + /* open isdn device */ + + if((isdnfd = open(I4BDEVICE, O_RDWR)) < 0) + { + log(LL_ERR, "main: cannot open %s: %s", I4BDEVICE, strerror(errno)); + exit(1); + } + + /* check kernel and userland have same version/release numbers */ + + if((ioctl(isdnfd, I4B_VR_REQ, &mvr)) < 0) + { + log(LL_ERR, "main: ioctl I4B_VR_REQ failed: %s", strerror(errno)); + do_exit(1); + } + + if(mvr.version != VERSION) + { + log(LL_ERR, "main: version mismatch, kernel %d, daemon %d", mvr.version, VERSION); + do_exit(1); + } + + if(mvr.release != REL) + { + log(LL_ERR, "main: release mismatch, kernel %d, daemon %d", mvr.release, REL); + do_exit(1); + } + + if(mvr.step != STEP) + { + log(LL_ERR, "main: step mismatch, kernel %d, daemon %d", mvr.step, STEP); + do_exit(1); + } + + /* init controller state array */ + + init_controller(); + + /* read runtime configuration file and configure ourselves */ + + configure(configfile, 0); + + if(config_error_flag) + { + log(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag); + exit(1); + } + + /* handle the rates stuff */ + + if((i = readrates(ratesfile)) == ERROR) + { + if(rate_error != NULL) + log(LL_ERR, "%s", rate_error); + exit(1); + } + + if(i == GOOD) + { + got_rate = 1; /* flag, ratesfile read and ok */ + DBGL(DL_MSG, (log(LL_DBG, "ratesfile %s read successfully", ratesfile))); + } + else + { + if(rate_error != NULL) + log(LL_WRN, "%s", rate_error); + } + + /* if writing accounting info, open file, set unbuffered */ + + if(useacctfile) + { + if((acctfp = fopen(acctfile, "a")) == NULL) + { + log(LL_ERR, "ERROR, can't open acctfile %s for writing, terminating!", acctfile); + exit(1); + } + setvbuf(acctfp, (char *)NULL, _IONBF, 0); + } + + /* initialize alias processing */ + + if(aliasing) + init_alias(aliasfile); + + /* init remote monitoring */ + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor) + { + monitor_init(); + sockfd = monitor_create_local_socket(); +#ifndef I4B_NOTCPIP_MONITOR + remotesockfd = monitor_create_remote_socket(monitorport); +#endif + } +#endif + + /* in case fullscreendisplay, initialize */ + +#ifdef USE_CURSES + if(do_fullscreen) + { + init_screen(); + } +#endif + + /* init realtime priority */ + +#ifdef USE_RTPRIO + if(rt_prio != RTPRIO_NOTUSED) + { + struct rtprio rtp; + + rtp.type = RTP_PRIO_REALTIME; + rtp.prio = rt_prio; + + if((rtprio(RTP_SET, getpid(), &rtp)) == -1) + { + log(LL_ERR, "rtprio failed: %s", strerror(errno)); + do_exit(1); + } + } +#endif + + srandom(580403); /* init random number gen */ + + mloop( /* enter loop of no return .. */ +#ifdef I4B_EXTERNAL_MONITOR + sockfd +#ifndef I4B_NOTCPIP_MONITOR + , remotesockfd +#endif +#endif + ); + do_exit(0); + return(0); +} + +/*---------------------------------------------------------------------------* + * program exit + *---------------------------------------------------------------------------*/ +void +do_exit(int exitval) +{ + close_allactive(); + + unlink(PIDFILE); + + log(LL_DMN, "daemon terminating, exitval = %d", exitval); + +#ifdef USE_CURSES + if(do_fullscreen) + endwin(); +#endif + +#ifdef I4B_EXTERNAL_MONITOR + monitor_exit(); +#endif + + exit(exitval); +} + +/*---------------------------------------------------------------------------* + * main loop + *---------------------------------------------------------------------------*/ +static void +mloop( +#ifdef I4B_EXTERNAL_MONITOR + int localmonitor +#ifndef I4B_NOTCPIP_MONITOR + , int remotemonitor +#endif +#endif +) +{ + fd_set set; + struct timeval timeout; + int ret; + int high_selfd; + + /* go into loop */ + + log(LL_DMN, "daemon started (pid = %d)", getpid()); + + for(;;) + { + FD_ZERO(&set); + +#ifdef USE_CURSES + if(do_fullscreen) + FD_SET(fileno(stdin), &set); +#endif + + FD_SET(isdnfd, &set); + + high_selfd = isdnfd; + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor) + { + if (localmonitor != -1) { + /* always watch for new connections */ + FD_SET(localmonitor, &set); + if(localmonitor > high_selfd) + high_selfd = localmonitor; + } +#ifndef I4B_NOTCPIP_MONITOR + if (remotemonitor != -1) { + FD_SET(remotemonitor, &set); + if(remotemonitor > high_selfd) + high_selfd = remotemonitor; + } +#endif + + /* if there are client connections, let monitor module + * enter them into the fdset */ + if(accepted) + { + monitor_prepselect(&set, &high_selfd); + } + } +#endif + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + ret = select(high_selfd + 1, &set, NULL, NULL, &timeout); + + if(ret > 0) + { + if(FD_ISSET(isdnfd, &set)) + isdnrdhdl(); + +#ifdef USE_CURSES + if(FD_ISSET(fileno(stdin), &set)) + kbdrdhdl(); +#endif + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor) + { + if(localmonitor != -1 && FD_ISSET(localmonitor, &set)) + monitor_handle_connect(localmonitor, 1); + +#ifndef I4B_NOTCPIP_MONITOR + if(remotemonitor != -1 && FD_ISSET(remotemonitor, &set)) + monitor_handle_connect(remotemonitor, 0); +#endif + if(accepted) + monitor_handle_input(&set); + } +#endif + } + else if(ret == -1) + { + if(errno != EINTR) + log(LL_WRN, "ERROR, select error on isdn device, errno = %d!", errno); + } + + /* handle timeout and recovery */ + + handle_recovery(); + } +} + +#ifdef USE_CURSES +/*---------------------------------------------------------------------------* + * data from keyboard available, read and process it + *---------------------------------------------------------------------------*/ +static void +kbdrdhdl(void) +{ + int ch = getch(); + + switch(ch) + { + case 0x0c: /* control L */ + wrefresh(curscr); + break; + + case '\n': + case '\r': + do_menu(); + break; + } +} +#endif + +/*---------------------------------------------------------------------------* + * data from /dev/isdn available, read and process them + *---------------------------------------------------------------------------*/ +static void +isdnrdhdl(void) +{ + static unsigned char msg_rd_buf[MSG_BUF_SIZ]; + msg_hdr_t *hp = (msg_hdr_t *)&msg_rd_buf[0]; + + register int len; + + if((len = read(isdnfd, msg_rd_buf, MSG_BUF_SIZ)) > 0) + { + switch(hp->type) + { + case MSG_CONNECT_IND: + msg_connect_ind((msg_connect_ind_t *)msg_rd_buf); + break; + + case MSG_CONNECT_ACTIVE_IND: + msg_connect_active_ind((msg_connect_active_ind_t *)msg_rd_buf); + break; + + case MSG_DISCONNECT_IND: + msg_disconnect_ind((msg_disconnect_ind_t *)msg_rd_buf); + break; + + case MSG_DIALOUT_IND: + msg_dialout((msg_dialout_ind_t *)msg_rd_buf); + break; + + case MSG_ACCT_IND: + msg_accounting((msg_accounting_ind_t *)msg_rd_buf); + break; + + case MSG_IDLE_TIMEOUT_IND: + msg_idle_timeout_ind((msg_idle_timeout_ind_t *)msg_rd_buf); + break; + + case MSG_CHARGING_IND: + msg_charging_ind((msg_charging_ind_t *)msg_rd_buf); + break; + + case MSG_PROCEEDING_IND: + msg_proceeding_ind((msg_proceeding_ind_t *)msg_rd_buf); + break; + + case MSG_ALERT_IND: + msg_alert_ind((msg_alert_ind_t *)msg_rd_buf); + break; + + case MSG_DRVRDISC_REQ: + msg_drvrdisc_req((msg_drvrdisc_req_t *)msg_rd_buf); + break; + + case MSG_L12STAT_IND: + msg_l12stat_ind((msg_l12stat_ind_t *)msg_rd_buf); + break; + + case MSG_TEIASG_IND: + msg_teiasg_ind((msg_teiasg_ind_t *)msg_rd_buf); + break; + + case MSG_PDEACT_IND: + msg_pdeact_ind((msg_pdeact_ind_t *)msg_rd_buf); + break; + + case MSG_NEGCOMP_IND: + msg_negcomplete_ind((msg_negcomplete_ind_t *)msg_rd_buf); + break; + + case MSG_IFSTATE_CHANGED_IND: + msg_ifstatechg_ind((msg_ifstatechg_ind_t *)msg_rd_buf); + break; + + default: + log(LL_WRN, "ERROR, unknown message received from /dev/isdn (0x%x)", msg_rd_buf[0]); + break; + } + } + else + { + log(LL_WRN, "ERROR, read error on isdn device, errno = %d, length = %d", errno, len); + } +} + +/*---------------------------------------------------------------------------* + * re-read the config file on SIGHUP or menu command + *---------------------------------------------------------------------------*/ +void +rereadconfig(int dummy) +{ + extern int entrycount; + + log(LL_DMN, "re-reading configuration file"); + + close_allactive(); + + entrycount = -1; + nentries = 0; + + /* read runtime configuration file and configure ourselves */ + + configure(configfile, 1); + + if(config_error_flag) + { + log(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag); + unlink(PIDFILE); + exit(1); + } + + if(aliasing) + { + /* reread alias database */ + free_aliases(); + init_alias(aliasfile); + } +} + +/*---------------------------------------------------------------------------* + * re-open the log/acct files on SIGUSR1 + *---------------------------------------------------------------------------*/ +void +reopenfiles(int dummy) +{ + if(useacctfile) + { + fflush(acctfp); + fclose(acctfp); + + if((acctfp = fopen(acctfile, "a")) == NULL) + { + log(LL_ERR, "ERROR, can't open acctfile %s for writing, terminating!", acctfile); + exit(1); + } + setvbuf(acctfp, (char *)NULL, _IONBF, 0); + } + + if(uselogfile) + { + finish_log(); + + if((logfp = fopen(logfile, "a")) == NULL) + { + fprintf(stderr, "ERROR, cannot open logfile %s: %s\n", + logfile, strerror(errno)); + exit(1); + } + + /* set unbuffered operation */ + + setvbuf(logfp, (char *)NULL, _IONBF, 0); + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/monitor.c b/usr.sbin/i4b/isdnd/monitor.c new file mode 100644 index 0000000..884df13 --- /dev/null +++ b/usr.sbin/i4b/isdnd/monitor.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - network monitor server module + * ------------------------------------------ + * + * $Id: monitor.c,v 1.6 1998/08/10 13:55:24 hm Exp $ + * + * last edit-date: [Fri Jul 17 18:07:00 1998] + * + * -mh created + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +#ifndef I4B_EXTERNAL_MONITOR +/* dummy version of routines needed by config file parser + * (config files should be valid with and without external montioring + * support compiled into the daemon) */ +void monitor_clear_rights() +{ } +int monitor_start_rights(const char *clientspec) +{ return I4BMAR_OK; } +void monitor_add_rights(int rights_mask) +{ } +void monitor_fixup_rights() +{ } +#else + +#include "monitor.h" +#include "vararray.h" +#include <sys/socket.h> +#include <sys/un.h> +#ifndef I4B_NOTCPIP_MONITOR +#include <netinet/in.h> +#include <arpa/inet.h> +#include <netdb.h> +#endif + +VARA_DECL(struct monitor_rights) rights = VARA_INITIALIZER; +#define INITIAL_RIGHTS_ALLOC 10 /* most users will have one or two entries */ + +static int local_rights = -1; /* index of entry for local socket, -1 if none */ + +/* for each active monitor connection we have one of this: */ +struct monitor_connection { + int sock; /* socket for this connection */ + int rights; /* active rights for this connection */ + int events; /* bitmask of events client is interested in */ +}; +static VARA_DECL(struct monitor_connection) connections = VARA_INITIALIZER; +#define INITIAL_CONNECTIONS_ALLOC 30 /* high guess */ + +/* derive channel number from config pointer */ +#define CHNO(cfgp) (((cfgp)->isdncontrollerused*2) + (cfgp)->isdnchannelused) + +/* local prototypes */ +static int cmp_rights(const void *a, const void *b); +static int monitor_command(int con_index, int fd, int rights); +static void cmd_dump_rights(int fd, int rights, BYTE *cmd); +static void cmd_dump_mcons(int fd, int rights, BYTE *cmd); +static void cmd_reread_cfg(int fd, int rights, BYTE *cmd); +static void cmd_hangup(int fd, int rights, BYTE *cmd); +static void monitor_broadcast(int mask, const BYTE *pkt, size_t bytes); +static int anybody(int mask); + +/* + * Due to the way we structure config files, the rights for an external + * monitor might be stated in multiple steps. First a call to + * monitor_start_rights opens an entry. Further (optional) calls to + * montior_add_rights assemble additional rights for this "current" + * entry. When closing the sys-file section of the config file, the + * "current" entry becomes invalid. + */ +static int cur_add_entry = -1; + +/* + * Initialize the monitor server module. This affects only active + * connections, the access rights are not modified here! + */ +void monitor_init() +{ + accepted = 0; + VARA_EMPTY(connections); +} + +/* + * Prepare for exit + */ +void monitor_exit() +{ + int i; + + /* Close all open connections. */ + VARA_FOREACH(connections, i) + close(VARA_AT(connections, i).sock); + + /* Remove their descriptions */ + VARA_EMPTY(connections); +} + +/* + * Initialize access rights. No active connections are affected! + */ +void monitor_clear_rights() +{ + VARA_EMPTY(rights); + cur_add_entry = -1; +} + +/* + * Add an entry to the access lists. The clientspec either is + * the name of the local socket or a host- or networkname or + * numeric ip/host-bit-len spec. + */ +int monitor_start_rights(const char *clientspec) +{ + int i; + struct monitor_rights r; + + /* initialize the new rights entry */ + memset(&r, 0, sizeof r); + + /* check clientspec */ + if (*clientspec == '/') { + struct sockaddr_un sa; + + /* this is a local socket spec, check if we already have one */ + if (VARA_VALID(rights, local_rights)) + return I4BMAR_DUP; + /* does it fit in a local socket address? */ + if (strlen(clientspec) > sizeof sa.sun_path) + return I4BMAR_LENGTH; + r.local = 1; + strcpy(r.name, clientspec); +#ifndef I4B_NOTCPIP_MONITOR + } else { + /* remote entry, parse host/net and cidr */ + char hostname[FILENAME_MAX]; + char *p; + p = strchr(clientspec, '/'); + if (!p) { + struct hostent *host; + u_int32_t hn; + /* must be a host spec */ + r.mask = ~0; + host = gethostbyname(clientspec); + if (!host) + return I4BMAR_NOIP; + memcpy(&hn, host->h_addr_list[0], sizeof hn); + r.net = (u_int32_t)ntohl(hn); + } else if (p[1]) { + /* must be net/cidr spec */ + int l; + struct netent *net; + u_int32_t s = ~0U; + int num = strtol(p+1, NULL, 10); + if (num < 0 || num > 32) + return I4BMAR_CIDR; + s >>= num; + s ^= ~0U; + l = p - clientspec; + if (l >= sizeof hostname) + return I4BMAR_LENGTH; + strncpy(hostname, clientspec, l); + hostname[l] = '\0'; + net = getnetbyname(hostname); + if (net == NULL) + r.net = (u_int32_t)inet_network(hostname); + else + r.net = (u_int32_t)net->n_net; + r.mask = s; + r.net &= s; + } else + return I4BMAR_CIDR; + + /* check for duplicate entry */ + VARA_FOREACH(rights, i) + if (VARA_AT(rights, i).mask == r.mask && + VARA_AT(rights, i).net == r.net && + VARA_AT(rights, i).local == r.local) + return I4BMAR_DUP; +#endif + } + r.rights = 0; + + /* entry ok, add it to the collection */ + cur_add_entry = i = VARA_NUM(rights); + VARA_ADD_AT(rights, i, struct monitor_rights, INITIAL_RIGHTS_ALLOC); + memcpy(&VARA_AT(rights, i), &r, sizeof r); + if (r.local) + local_rights = i; + + log(LL_DBG, "system: monitor = %s", clientspec); + + return I4BMAR_OK; +} + +/* + * Add rights to the currently constructed entry - if any. + */ +void monitor_add_rights(int rights_mask) +{ + if (cur_add_entry < 0) return; /* noone under construction */ + + VARA_AT(rights, cur_add_entry).rights |= rights_mask; + + log(LL_DBG, "system: monitor-access = 0x%x", rights_mask); +} + +/* + * All rights have been added now. Sort the to get most specific + * host/net masks first, so we can travel the list and use the first + * match for actual rights. + */ +void monitor_fixup_rights() +{ + int i; + + /* no more rights may be added to the current entry */ + cur_add_entry = -1; + + /* sort the rights array */ + qsort(VARA_PTR(rights), VARA_NUM(rights), sizeof(struct monitor_rights), cmp_rights); + + /* now the local entry may have moved, update its index */ + if (VARA_VALID(rights, local_rights)) { + local_rights = -1; + VARA_FOREACH(rights, i) { + if (VARA_AT(rights, i).local) { + local_rights = i; + break; + } + } + } +} + +/* comparator for rights */ +static int cmp_rights(const void *a, const void *b) +{ + u_int32_t mask; + struct monitor_rights const * pa = (struct monitor_rights const*)a; + struct monitor_rights const * pb = (struct monitor_rights const*)b; + + /* local sorts first */ + if (pa->local) + return -1; + + /* which is the less specific netmask? */ + mask = pa->mask; + if ((pb->mask & mask) == 0) + mask = pb->mask; + /* are the entries disjunct? */ + if ((pa->net & mask) != (pb->net & mask)) { + /* simply compare net part of address */ + return ((pa->net & mask) < (pb->net & mask)) ? -1 : 1; + } + /* One entry is part of the others net. We already now "mask" is + * the netmask of the less specific (i.e. greater) one */ + return (pa->mask == mask) ? 1 : -1; +} + +#ifndef I4B_NOTCPIP_MONITOR +/* + * Check if access rights for a remote socket are specified and + * create this socket. Return -1 otherwise. + */ +int monitor_create_remote_socket(int portno) +{ + struct sockaddr_in sa; + int val; + int remotesockfd = socket(AF_INET, SOCK_STREAM, 0); + if (remotesockfd == -1) { + log(LL_ERR, "could not create remote monitor socket, errno = %d", errno); + exit(1); + } + val = 1; + if (setsockopt(remotesockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof val)) { + log(LL_ERR, "could not setsockopt, errno = %d", errno); + exit(1); + } + memset(&sa, 0, sizeof sa); + sa.sin_len = sizeof sa; + sa.sin_family = AF_INET; + sa.sin_port = htons(portno); + sa.sin_addr.s_addr = htonl(INADDR_ANY); + if (bind(remotesockfd, (struct sockaddr *)&sa, sizeof sa) == -1) { + log(LL_ERR, "could not bind remote monitor socket to port %d, errno = %d", portno, errno); + exit(1); + } + if (listen(remotesockfd, 0)) { + log(LL_ERR, "could not listen on monitor socket, errno = %d", errno); + exit(1); + } + + return remotesockfd; +} +#endif + +/* + * Check if access rights for a local socket are specified and + * create this socket. Return -1 otherwise. + */ +int monitor_create_local_socket() +{ + int s; + struct sockaddr_un sa; + + /* check for a local entry */ + if (!VARA_VALID(rights, local_rights)) + return -1; + + /* create and setup socket */ + s = socket(AF_LOCAL, SOCK_STREAM, 0); + if (s == -1) { + log(LL_ERR, "could not create local monitor socket, errno = %d", errno); + exit(1); + } + unlink(VARA_AT(rights, local_rights).name); + memset(&sa, 0, sizeof sa); + sa.sun_len = sizeof sa; + sa.sun_family = AF_LOCAL; + strcpy(sa.sun_path, VARA_AT(rights, local_rights).name); + if (bind(s, (struct sockaddr *)&sa, sizeof sa)) { + log(LL_ERR, "could not bind local monitor socket [%s], errno = %d", VARA_AT(rights, local_rights).name, errno); + exit(1); + } + if (listen(s, 0)) { + log(LL_ERR, "could not listen on local monitor socket, errno = %d", errno); + exit(1); + } + + return s; +} + +/* + * Prepare a fd_set for a select call. Add all our local + * filedescriptors to the set, increment max_fd if appropriate. + */ +void monitor_prepselect(fd_set *selset, int *max_fd) +{ + int i; + + VARA_FOREACH(connections, i) { + int fd = VARA_AT(connections, i).sock; + if (fd > *max_fd) + *max_fd = fd; + FD_SET(fd, selset); + } +} + +/* + * Check if the result from a select call indicates something + * to do for us. + */ +void monitor_handle_input(fd_set *selset) +{ + int i; + + VARA_FOREACH(connections, i) { + int fd = VARA_AT(connections, i).sock; + if (FD_ISSET(fd, selset)) { + /* handle command from this client */ + if (monitor_command(i, fd, VARA_AT(connections, i).rights) != 0) { + /* broken or closed connection */ + log(LL_DBG, "monitor connection #%d closed", i); + VARA_REMOVEAT(connections, i); + i--; + } + } + } + + /* all connections gone? */ + if (VARA_NUM(connections) == 0) + accepted = 0; +} + +/* + * Try new incoming connection on the given socket. + * Setup client descriptor and send initial data. + */ +void monitor_handle_connect(int sockfd, int is_local) +{ + struct monitor_connection *con; +#ifndef I4B_NOTCPIP_MONITOR + struct sockaddr_in ia; + u_int32_t ha = 0; +#endif + struct sockaddr_un ua; + BYTE idata[I4B_MON_IDATA_SIZE]; + int fd = -1, s, i, r_mask; + char source[FILENAME_MAX]; + + /* accept the connection */ + if (is_local) { + s = sizeof ua; + fd = accept(sockfd, (struct sockaddr *)&ua, &s); + strcpy(source, "local connection"); +#ifndef I4B_NOTCPIP_MONITOR + } else { + s = sizeof ia; + fd = accept(sockfd, (struct sockaddr *)&ia, &s); + snprintf(source, sizeof source, "tcp/ip connection from %s\n", + inet_ntoa(ia.sin_addr)); + memcpy(&ha, &ia.sin_addr.s_addr, sizeof ha); + ha = ntohl(ha); +#endif + } + + /* check the access rights of this connection */ + r_mask = 0; + VARA_FOREACH(rights, i) { + struct monitor_rights *r = &VARA_AT(rights, i); + if (r->local) { + if (is_local) { + r_mask = r->rights; + break; + } +#ifndef I4B_NOTCPIP_MONITOR + } else { + if ((ha & r->mask) == r->net) { + r_mask = r->rights; + break; + } +#endif + } + } + + if (r_mask == 0) { + /* no rights - go away */ + log(LL_DBG, "monitor access denied: %s", source); + close(fd); + return; + } + + accepted = 1; + i = VARA_NUM(connections); + VARA_ADD_AT(connections, i, struct monitor_connection, INITIAL_CONNECTIONS_ALLOC); + con = &VARA_AT(connections, i); + memset(con, 0, sizeof *con); + con->sock = fd; + con->rights = r_mask; + log(LL_DBG, "monitor access granted, rights = %x, #%d, %s", + r_mask, i, source); + + /* send initial data */ + I4B_PREP_CMD(idata, I4B_MON_IDATA_CODE); + I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMAJOR, MPROT_VERSION); + I4B_PUT_2B(idata, I4B_MON_IDATA_VERSMINOR, MPROT_REL); + I4B_PUT_2B(idata, I4B_MON_IDATA_NUMCTRL, ncontroller); + I4B_PUT_4B(idata, I4B_MON_IDATA_CLACCESS, r_mask); + write(fd, idata, sizeof idata); + + for (i = 0; i < ncontroller; i++) { + BYTE ictrl[I4B_MON_ICTRL_SIZE]; + I4B_PREP_CMD(ictrl, I4B_MON_ICTRL_CODE); + I4B_PUT_STR(ictrl, I4B_MON_ICTRL_NAME, name_of_controller(isdn_ctrl_tab[i].ctrl_type, isdn_ctrl_tab[i].card_type)); + I4B_PUT_2B(ictrl, I4B_MON_ICTRL_BUSID, 0); + I4B_PUT_4B(ictrl, I4B_MON_ICTRL_FLAGS, 0); + I4B_PUT_4B(ictrl, I4B_MON_ICTRL_NCHAN, 2); + write(fd, ictrl, sizeof ictrl); + } +} + +/* dump all monitor rights */ +static void cmd_dump_rights(int fd, int r_mask, BYTE *cmd) +{ + int i; + BYTE drini[I4B_MON_DRINI_SIZE]; + BYTE dr[I4B_MON_DR_SIZE]; + + I4B_PREP_EVNT(drini, I4B_MON_DRINI_CODE); + I4B_PUT_2B(drini, I4B_MON_DRINI_COUNT, VARA_NUM(rights)); + write(fd, drini, sizeof drini); + + VARA_FOREACH(rights, i) { + I4B_PREP_EVNT(dr, I4B_MON_DR_CODE); + I4B_PUT_4B(dr, I4B_MON_DR_RIGHTS, VARA_AT(rights, i).rights); + I4B_PUT_4B(dr, I4B_MON_DR_NET, VARA_AT(rights, i).net); + I4B_PUT_4B(dr, I4B_MON_DR_MASK, VARA_AT(rights, i).mask); + I4B_PUT_1B(dr, I4B_MON_DR_LOCAL, VARA_AT(rights, i).local); + write(fd, dr, sizeof dr); + } +} + +/* rescan config file */ +static void cmd_reread_cfg(int fd, int rights, BYTE *cmd) +{ + rereadconfig(42); +} + +/* drop one connection */ +static void cmd_hangup(int fd, int rights, BYTE *cmd) +{ + int channel = I4B_GET_4B(cmd, I4B_MON_HANGUP_CHANNEL); + hangup_channel(channel); +} + +/* dump all active monitor connections */ +static void cmd_dump_mcons(int fd, int rights, BYTE *cmd) +{ + int i; + BYTE dcini[I4B_MON_DCINI_SIZE]; + + I4B_PREP_EVNT(dcini, I4B_MON_DCINI_CODE); + I4B_PUT_2B(dcini, I4B_MON_DCINI_COUNT, VARA_NUM(connections)); + write(fd, dcini, sizeof dcini); + + VARA_FOREACH(connections, i) { +#ifndef I4B_NOTCPIP_MONITOR + int namelen; + struct sockaddr_in name; +#endif + BYTE dc[I4B_MON_DC_SIZE]; + + I4B_PREP_EVNT(dc, I4B_MON_DC_CODE); + I4B_PUT_4B(dc, I4B_MON_DC_RIGHTS, VARA_AT(connections, i).rights); +#ifndef I4B_NOTCPIP_MONITOR + namelen = sizeof name; + if (getpeername(VARA_AT(connections, i).sock, (struct sockaddr*)&name, &namelen) == 0) + memcpy(dc+I4B_MON_DC_WHO, &name.sin_addr, sizeof name.sin_addr); +#endif + write(fd, dc, sizeof dc); + } +} + +/* + * Handle a command from the given socket. The client + * has rights as specified in the rights parameter. + * Return non-zero if connection is closed. + */ +static int monitor_command(int con_index, int fd, int rights) +{ + char cmd[I4B_MAX_MON_CLIENT_CMD]; + u_int code; + /* command dispatch table */ + typedef void (*cmd_func_t)(int fd, int rights, BYTE *cmd); + static struct { + cmd_func_t call; /* function to execute */ + u_int rights; /* necessary rights */ + } cmd_tab[] = + { + /* 0 */ { NULL, 0 }, + /* 1 */ { cmd_dump_rights, I4B_CA_COMMAND_FULL }, + /* 2 */ { cmd_dump_mcons, I4B_CA_COMMAND_FULL }, + /* 3 */ { cmd_reread_cfg, I4B_CA_COMMAND_FULL }, + /* 4 */ { cmd_hangup, I4B_CA_COMMAND_FULL }, + }; +#define NUMCMD (sizeof cmd_tab / sizeof cmd_tab[0]) + + u_long u; + int bytes; + + /* Network transfer may deliver two or more packets concatenated. + * Peek at the header and read only one event at a time... */ + ioctl(fd, FIONREAD, &u); + if (u < I4B_MON_CMD_HDR) { + if (u == 0) { + /* socket closed by peer */ + close(fd); + return 1; + } + return 0; /* not enough data there yet */ + } + bytes = recv(fd, cmd, I4B_MON_CMD_HDR, MSG_PEEK); + if (bytes < I4B_MON_CMD_HDR) + return 0; /* errh? something must be wrong... */ + bytes = I4B_GET_2B(cmd, I4B_MON_CMD_LEN); + if (bytes >= sizeof cmd) { + close(fd); + log(LL_ERR, "garbage on monitor connection #%d, closing it", con_index); + return 1; + } + /* now we know the size, it fits, so lets read it! */ + if (read(fd, cmd, bytes) <= 0) { + close(fd); + return 1; + } + + /* decode command */ + code = I4B_GET_2B(cmd, I4B_MON_CMD); + + /* special case: may modify our connection descriptor, is + * beyound all rights checks */ + if (code == I4B_MON_CCMD_SETMASK) { + /* + u_int major = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMAJOR); + u_int minor = I4B_GET_2B(cmd, I4B_MON_ICLIENT_VERMINOR); + */ + int events = I4B_GET_4B(cmd, I4B_MON_ICLIENT_EVENTS); + VARA_AT(connections, con_index).events = events & rights; + return 0; + } + + if (code < 0 || code >= NUMCMD) { + log(LL_ERR, "illegal command from client #%d: code = %d\n", + con_index, code); + return 0; + } + if (cmd_tab[code].call == NULL) + return 0; + if ((cmd_tab[code].rights & rights) == cmd_tab[code].rights) + cmd_tab[code].call(fd, rights, cmd); + + return 0; +} + +/* + * Check if somebody would receive an event with this mask. + * We are lazy and try to avoid assembling unneccesary packets. + * Return 0 if no one interested, nonzero otherwise. + */ +static int anybody(int mask) +{ + int i; + + VARA_FOREACH(connections, i) + if ((VARA_AT(connections, i).events & mask) == mask) + return 1; + + return 0; +} + +/* + * Send an event to every connection interested in this kind of + * event + */ +static void monitor_broadcast(int mask, const BYTE *pkt, size_t bytes) +{ + int i; + + VARA_FOREACH(connections, i) { + if ((VARA_AT(connections, i).events & mask) == mask) { + int fd = VARA_AT(connections, i).sock; + write(fd, pkt, bytes); + } + } +} + +/* + * Post a logfile event + */ +void monitor_evnt_log(int prio, const char * what, const char * msg) +{ + BYTE evnt[I4B_MON_LOGEVNT_SIZE]; + time_t now; + + if (!anybody(I4B_CA_EVNT_I4B)) return; + + time(&now); + I4B_PREP_EVNT(evnt, I4B_MON_LOGEVNT_CODE); + I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_TSTAMP, (long)now); + I4B_PUT_4B(evnt, I4B_MON_LOGEVNT_PRIO, prio); + I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_WHAT, what); + I4B_PUT_STR(evnt, I4B_MON_LOGEVNT_MSG, msg); + + monitor_broadcast(I4B_CA_EVNT_I4B, evnt, sizeof evnt); +} + +/* + * Post a charging event on the connection described + * by the given config entry. + */ +void monitor_evnt_charge(cfg_entry_t *cep, int units, int estimate) +{ + int chno = CHNO(cep); + int mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT; + time_t now; + BYTE evnt[I4B_MON_CHRG_SIZE]; + + if (!anybody(mask)) return; + + time(&now); + I4B_PREP_EVNT(evnt, I4B_MON_CHRG_CODE); + I4B_PUT_4B(evnt, I4B_MON_CHRG_TSTAMP, (long)now); + I4B_PUT_4B(evnt, I4B_MON_CHRG_CHANNEL, chno); + I4B_PUT_4B(evnt, I4B_MON_CHRG_UNITS, units); + I4B_PUT_4B(evnt, I4B_MON_CHRG_ESTIMATED, estimate ? 1 : 0); + + monitor_broadcast(mask, evnt, sizeof evnt); +} + +/* + * Post a connection event + */ +void monitor_evnt_connect(cfg_entry_t *cep) +{ + BYTE evnt[I4B_MON_CONNECT_SIZE]; + char devname[I4B_MAX_MON_STRING]; + int chno = CHNO(cep); + int mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT; + time_t now; + + if (!anybody(mask)) return; + + time(&now); + snprintf(devname, sizeof devname, "%s%d", bdrivername(cep->usrdevicename), cep->usrdeviceunit); + I4B_PREP_EVNT(evnt, I4B_MON_CONNECT_CODE); + I4B_PUT_4B(evnt, I4B_MON_CONNECT_TSTAMP, (long)now); + I4B_PUT_4B(evnt, I4B_MON_CONNECT_DIR, cep->direction == DIR_OUT ? 1 : 0); + I4B_PUT_4B(evnt, I4B_MON_CONNECT_CHANNEL, chno); + I4B_PUT_STR(evnt, I4B_MON_CONNECT_CFGNAME, cep->name); + I4B_PUT_STR(evnt, I4B_MON_CONNECT_DEVNAME, devname); + I4B_PUT_STR(evnt, I4B_MON_CONNECT_REMPHONE, cep->real_phone_incoming); + I4B_PUT_STR(evnt, I4B_MON_CONNECT_LOCPHONE, cep->remote_phone_dialout); + + monitor_broadcast(mask, evnt, sizeof evnt); +} + +/* + * Post a disconnect event + */ +void monitor_evnt_disconnect(cfg_entry_t *cep) +{ + BYTE evnt[I4B_MON_DISCONNECT_SIZE]; + int chno = CHNO(cep); + int mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT; + time_t now; + + if (!anybody(mask)) return; + + time(&now); + I4B_PREP_EVNT(evnt, I4B_MON_DISCONNECT_CODE); + I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_TSTAMP, (long)now); + I4B_PUT_4B(evnt, I4B_MON_DISCONNECT_CHANNEL, chno); + + monitor_broadcast(mask, evnt, sizeof evnt); +} + +/* + * Post an up/down event + */ +void monitor_evnt_updown(cfg_entry_t *cep, int up) +{ + BYTE evnt[I4B_MON_UPDOWN_SIZE]; + int chno = CHNO(cep); + int mask = (cep->direction == DIR_IN) ? I4B_CA_EVNT_CALLIN : I4B_CA_EVNT_CALLOUT; + time_t now; + + if (!anybody(mask)) return; + + time(&now); + I4B_PREP_EVNT(evnt, I4B_MON_UPDOWN_CODE); + I4B_PUT_4B(evnt, I4B_MON_UPDOWN_TSTAMP, (long)now); + I4B_PUT_4B(evnt, I4B_MON_UPDOWN_CHANNEL, chno); + I4B_PUT_4B(evnt, I4B_MON_UPDOWN_ISUP, up); + + monitor_broadcast(mask, evnt, sizeof evnt); +} + +void hangup_channel(int channel) +{ + int i; + cfg_entry_t * cep = NULL; + + for (i = 0; i < ncontroller; i++) + { + if(isdn_ctrl_tab[i].state != CTRL_UP) + continue; + if(isdn_ctrl_tab[i].stateb1 != CHAN_IDLE) + { + cep = get_cep_by_cc(i, 0); + if (cep != NULL && CHNO(cep) == channel) + goto found; + } + if(isdn_ctrl_tab[i].stateb2 != CHAN_IDLE) + { + cep = get_cep_by_cc(i, 1); + if (cep != NULL && CHNO(cep) == channel) + goto found; + } + } + /* not found */ + return; + +found: + cep->hangup = 1; + return; +} + +#endif /* I4B_EXTERNAL_MONITOR */ diff --git a/usr.sbin/i4b/isdnd/msghdl.c b/usr.sbin/i4b/isdnd/msghdl.c new file mode 100644 index 0000000..61ac0ed --- /dev/null +++ b/usr.sbin/i4b/isdnd/msghdl.c @@ -0,0 +1,983 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - message from kernel handling routines + * -------------------------------------------------- + * + * $Id: msghdl.c,v 1.54 1998/12/19 09:03:16 hm Exp $ + * + * last edit-date: [Sat Dec 19 09:57:16 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +/*---------------------------------------------------------------------------* + * handle incoming CONNECT_IND (=SETUP) message + *---------------------------------------------------------------------------*/ +void +msg_connect_ind(msg_connect_ind_t *mp) +{ + cfg_entry_t *cep; + char *src_tela = "ERROR-src_tela"; + char *dst_tela = "ERROR-dst_tela"; + +#define SRC (aliasing == 0 ? mp->src_telno : src_tela) +#define DST (aliasing == 0 ? mp->dst_telno : dst_tela) + + if((cep = find_matching_entry_incoming(mp)) == NULL) + { + /* log message generated in find_matching_entry_incoming() */ + sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0); + return; + } + + if(cep->cdid != CDID_UNUSED && cep->cdid != CDID_RESERVED) + { + /* + * This is an incoming call on a number we just dialed out. + * Stop our dial-out and accept the incoming call. + */ + if(cep->saved_call.cdid != CDID_UNUSED && + cep->saved_call.cdid != CDID_RESERVED) + { + int cdid; + + /* disconnect old, not new */ + + cdid = cep->cdid; + cep->cdid = cep->saved_call.cdid; + sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + cep->cdid = cdid; + + /* + * Shortcut the state machine and mark this + * entry as free + */ +/* XXX */ cep->state = ST_IDLE; /* this is an invalid */ + /* transition, */ + /* so no next_state() */ + /* we have to wait here for an incoming */ + /* disconnect message !!! (-hm) */ + } + } + + if(aliasing) + { + src_tela = get_alias(mp->src_telno); + dst_tela = get_alias(mp->dst_telno); + } + + if(cep->inout == DIR_OUTONLY) + { + log(LL_CHD, "%05d %s incoming call from %s to %s not allowed by configuration!", + mp->header.cdid, cep->name, SRC, DST); + sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0); + return; + } + + cep->charge = 0; + cep->last_charge = 0; + + switch(cep->dialin_reaction) + { + case REACT_ACCEPT: + log(LL_CHD, "%05d %s accepting: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + decr_free_channels(mp->controller); + next_state(cep, EV_MCI); + break; + + case REACT_REJECT: + log(LL_CHD, "%05d %s rejecting: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT, + (CAUSET_I4B << 8) | CAUSE_I4B_REJECT); + cep->cdid = CDID_UNUSED; + break; + + case REACT_IGNORE: + log(LL_CHD, "%05d %s ignoring: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0); + break; + + case REACT_ANSWER: + decr_free_channels(mp->controller); + if(cep->alert) + { + if(mp->display) + { + log(LL_CHD, "%05d %s alerting: incoming call from %s to %s (%s)", + mp->header.cdid, cep->name, SRC, DST, mp->display); + } + else + { + log(LL_CHD, "%05d %s alerting: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + } + next_state(cep, EV_ALRT); + } + else + { + if(mp->display) + { + log(LL_CHD, "%05d %s answering: incoming call from %s to %s (%s)", + mp->header.cdid, cep->name, SRC, DST, mp->display); + } + else + { + log(LL_CHD, "%05d %s answering: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + } + next_state(cep, EV_MCI); + } + break; + + case REACT_CALLBACK: +#ifdef NOTDEF +/*XXX reserve channel ??? */ decr_free_channels(mp->controller); +#endif + if(cep->cdid == CDID_RESERVED) + { + log(LL_CHD, "%05d %s reserved: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + /* no state change */ + } + else + { + log(LL_CHD, "%05d %s callback: incoming call from %s to %s", + mp->header.cdid, cep->name, SRC, DST); + sendm_connect_resp(cep, mp->header.cdid, SETUP_RESP_REJECT, + (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + cep->last_release_time = time(NULL); + cep->cdid = CDID_RESERVED; + next_state(cep, EV_CBRQ); + } + break; + + default: + log(LL_WRN, "msg_connect_ind: unknown response type, tx SETUP_RESP_DNTCRE"); + sendm_connect_resp(NULL, mp->header.cdid, SETUP_RESP_DNTCRE, 0); + break; + } +#undef SRC +#undef DST +} + +/*---------------------------------------------------------------------------* + * handle incoming CONNECT_ACTIVE_IND message + *---------------------------------------------------------------------------*/ +void +msg_connect_active_ind(msg_connect_active_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_connect_active_ind: cdid not found!"); + return; + } + + cep->isdncontrollerused = mp->controller; + cep->isdnchannelused = mp->channel; + + cep->aoc_now = cep->connect_time = time(NULL); + cep->aoc_last = 0; + cep->aoc_diff = 0; + cep->aoc_valid = AOC_INVALID; + + cep->local_disconnect = DISCON_REM; + + cep->inbytes = INVALID; + cep->outbytes = INVALID; + cep->hangup = 0; + + /* set the B-channel to active */ + + if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR) + log(LL_ERR, "msg_connect_active_ind: set_channel_busy failed!"); + + if(cep->direction == DIR_OUT) + { + log(LL_CHD, "%05d %s outgoing call active (ctl %d, ch %d)", + cep->cdid, cep->name, + cep->isdncontrollerused, cep->isdnchannelused); + } + else + { + log(LL_CHD, "%05d %s incoming call active (ctl %d, ch %d)", + cep->cdid, cep->name, + cep->isdncontrollerused, cep->isdnchannelused); + } + +#ifdef USE_CURSES + if(do_fullscreen) + display_connect(cep); +#endif +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor && accepted) + monitor_evnt_connect(cep); +#endif + + if(isdntime && (mp->datetime[0] != '\0')) + { + log(LL_DMN, "date/time from exchange = %s", mp->datetime); + } + + next_state(cep, EV_MCAI); +} + +/*---------------------------------------------------------------------------* + * handle incoming PROCEEDING_IND message + *---------------------------------------------------------------------------*/ +void +msg_proceeding_ind(msg_proceeding_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_proceeding_ind: cdid not found!"); + return; + } + + cep->isdncontrollerused = mp->controller; + cep->isdnchannelused = mp->channel; + + /* set the B-channels active */ + + if((set_channel_busy(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR) + log(LL_ERR, "msg_proceeding_ind: set_channel_busy failed!"); + + log(LL_CHD, "%05d %s outgoing call proceeding (ctl %d, ch %d)", + cep->cdid, cep->name, + cep->isdncontrollerused, cep->isdnchannelused); +} + +/*---------------------------------------------------------------------------* + * handle incoming ALERT_IND message + *---------------------------------------------------------------------------*/ +void +msg_alert_ind(msg_alert_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_alert_ind: cdid not found!"); + return; + } +#ifdef NOTDEF + log(LL_CHD, "%05d %s incoming alert", cep->cdid, cep->name); +#endif +} + +/*---------------------------------------------------------------------------* + * handle incoming L12STAT_IND message + *---------------------------------------------------------------------------*/ +void +msg_l12stat_ind(msg_l12stat_ind_t *ml) +{ +#ifdef USE_CURSES + if(do_fullscreen) + display_l12stat(ml->controller, ml->layer, ml->state); +#endif + + DBGL(DL_CNST, (log(LL_DBG, "msg_l12stat_ind: unit %d, layer %d, state %d", + ml->controller, ml->layer, ml->state))); +} + +/*---------------------------------------------------------------------------* + * handle incoming TEIASG_IND message + *---------------------------------------------------------------------------*/ +void +msg_teiasg_ind(msg_teiasg_ind_t *mt) +{ +#ifdef USE_CURSES + if(do_fullscreen) + display_tei(mt->controller, mt->tei); +#endif + + DBGL(DL_CNST, (log(LL_DBG, "msg_teiasg_ind: unit %d, tei = %d", + mt->controller, mt->tei))); +} + +/*---------------------------------------------------------------------------* + * handle incoming L12STAT_IND message + *---------------------------------------------------------------------------*/ +void +msg_pdeact_ind(msg_pdeact_ind_t *md) +{ + int i; + int ctrl = md->controller; + cfg_entry_t *cep; + +#ifdef USE_CURSES + if(do_fullscreen) + { + display_l12stat(ctrl, LAYER_ONE, LAYER_IDLE); + display_l12stat(ctrl, LAYER_TWO, LAYER_IDLE); + display_tei(ctrl, -1); + } +#endif + + DBGL(DL_CNST, (log(LL_DBG, "msg_pdeact_ind: unit %d, persistent deactivation", ctrl))); + + for(i=0; i < nentries; i++) + { + if((cfg_entry_tab[i].cdid != CDID_UNUSED) && + (cfg_entry_tab[i].isdncontrollerused == ctrl)) + { + cep = &cfg_entry_tab[i]; + + if(cep->cdid == CDID_RESERVED) + { + cep->cdid = CDID_UNUSED; + continue; + } + + cep->cdid = CDID_UNUSED; + + cep->last_release_time = time(NULL); + + SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B); + SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_L1ERROR); + + if(cep->direction == DIR_OUT) + { + log(LL_CHD, "%05d %s outgoing call disconnected (local)", + cep->cdid, cep->name); + } + else + { + log(LL_CHD, "%05d %s incoming call disconnected (local)", + cep->cdid, cep->name); + } + + log(LL_CHD, "%05d %s cause %s", + cep->cdid, cep->name, print_i4b_cause(cep->disc_cause)); + +#ifdef USE_CURSES + if(do_fullscreen && (cep->connect_time > 0)) + display_disconnect(cep); +#endif + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor && accepted) + monitor_evnt_disconnect(cep); +#endif + if(cep->disconnectprog) + exec_connect_prog(cep, cep->disconnectprog, 1); + + if(cep->connect_time > 0) + { + if(cep->direction == DIR_OUT) + { + log(LL_CHD, "%05d %s charging: %d units, %d seconds", + cep->cdid, cep->name, cep->charge, + (int)difftime(time(NULL), cep->connect_time)); + } + else + { + log(LL_CHD, "%05d %s connected %d seconds", + cep->cdid, cep->name, + (int)difftime(time(NULL), cep->connect_time)); + } + + if((cep->inbytes != INVALID) && (cep->outbytes != INVALID)) + { + if((cep->ioutbytes != cep->outbytes) || + (cep->iinbytes != cep->inbytes)) + { + log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)", + cep->cdid, cep->name, + cep->inbytes, cep->outbytes, + cep->iinbytes, cep->ioutbytes); + } + else + { + log(LL_CHD, "%05d %s accounting: in %d, out %d", + cep->cdid, cep->name, + cep->inbytes, cep->outbytes); + } + } + } + + if(useacctfile && (cep->connect_time > 0)) + { + int con_secs; + char logdatetime[41]; + struct tm *tp; + + con_secs = difftime(time(NULL), cep->connect_time); + + tp = localtime(&cep->connect_time); + + strftime(logdatetime,40,I4B_TIME_FORMAT,tp); + + if(cep->inbytes != INVALID && cep->outbytes != INVALID) + { + fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n", + logdatetime, getlogdatetime(), + cep->name, cep->charge, con_secs, + cep->inbytes, cep->outbytes); + } + else + { + fprintf(acctfp, "%s - %s %s %d (%d)\n", + logdatetime, getlogdatetime(), + cep->name, cep->charge, con_secs); + } + } + + /* set the B-channel inactive */ + + if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR) + log(LL_ERR, "msg_pdeact_ind: set_channel_idle failed!"); + + incr_free_channels(cep->isdncontrollerused); + + cep->connect_time = 0; + } + } +} + +/*---------------------------------------------------------------------------* + * handle incoming NEGCOMP_IND message + *---------------------------------------------------------------------------*/ +void +msg_negcomplete_ind(msg_negcomplete_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_negcomp_ind: cdid not found"); + return; + } + + if(cep->connectprog) + exec_connect_prog(cep, cep->connectprog, 0); +} + +/*---------------------------------------------------------------------------* + * handle incoming IFSTATE_CHANGED indication + *---------------------------------------------------------------------------*/ +void +msg_ifstatechg_ind(msg_ifstatechg_ind_t *mp) +{ + cfg_entry_t *cep; + char *device; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_negcomp_ind: cdid not found"); + return; + } + + device = bdrivername(cep->usrdevicename); + log(LL_DBG, "%s%d: switched to state %d\n", device, cep->usrdeviceunit, mp->state); +} + +/*---------------------------------------------------------------------------* + * handle incoming DISCONNECT_IND message + *---------------------------------------------------------------------------*/ +void +msg_disconnect_ind(msg_disconnect_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_disconnect_ind: cdid not found"); + return; + } + + /* is this an aborted out-call prematurely called back? */ + if (cep->saved_call.cdid == mp->header.cdid) + { + DBGL(DL_CNST, (log(LL_DBG, "aborted outcall %05d disconnected", + mp->header.cdid))); + cep->saved_call.cdid = CDID_UNUSED; + + if((set_channel_idle(cep->saved_call.controller, cep->saved_call.channel)) == ERROR) + log(LL_ERR, "msg_disconnect_ind: set_channel_idle failed!"); + + incr_free_channels(cep->saved_call.controller); + return; + } + + cep->last_release_time = time(NULL); + cep->disc_cause = mp->cause; + + if(cep->direction == DIR_OUT) + { + log(LL_CHD, "%05d %s outgoing call disconnected %s", + cep->cdid, cep->name, + cep->local_disconnect == DISCON_LOC ? + "(local)" : "(remote)"); + } + else + { + log(LL_CHD, "%05d %s incoming call disconnected %s", + cep->cdid, cep->name, + cep->local_disconnect == DISCON_LOC ? + "(local)" : "(remote)"); + } + + log(LL_CHD, "%05d %s cause %s", + cep->cdid, cep->name, print_i4b_cause(mp->cause)); + +#ifdef USE_CURSES + if(do_fullscreen && (cep->connect_time > 0)) + display_disconnect(cep); +#endif + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor && accepted) + monitor_evnt_disconnect(cep); +#endif + + if(cep->disconnectprog) + exec_connect_prog(cep, cep->disconnectprog, 1); + + if(cep->connect_time > 0) + { + if(cep->direction == DIR_OUT) + { + log(LL_CHD, "%05d %s charging: %d units, %d seconds", + cep->cdid, cep->name, cep->charge, + (int)difftime(time(NULL), cep->connect_time)); + } + else + { + log(LL_CHD, "%05d %s connected %d seconds", + cep->cdid, cep->name, + (int)difftime(time(NULL), cep->connect_time)); + } + + if((cep->inbytes != INVALID) && (cep->outbytes != INVALID)) + { + if((cep->ioutbytes != cep->outbytes) || + (cep->iinbytes != cep->inbytes)) + { + log(LL_CHD, "%05d %s accounting: in %d, out %d (in %d, out %d)", + cep->cdid, cep->name, + cep->inbytes, cep->outbytes, + cep->iinbytes, cep->ioutbytes); + } + else + { + log(LL_CHD, "%05d %s accounting: in %d, out %d", + cep->cdid, cep->name, + cep->inbytes, cep->outbytes); + } + } + } + + if(useacctfile && (cep->connect_time > 0)) + { + int con_secs; + char logdatetime[41]; + struct tm *tp; + + con_secs = difftime(time(NULL), cep->connect_time); + + tp = localtime(&cep->connect_time); + + strftime(logdatetime,40,I4B_TIME_FORMAT,tp); + + if(cep->inbytes != INVALID && cep->outbytes != INVALID) + { + fprintf(acctfp, "%s - %s %s %d (%d) (%d/%d)\n", + logdatetime, getlogdatetime(), + cep->name, cep->charge, con_secs, + cep->inbytes, cep->outbytes); + } + else + { + fprintf(acctfp, "%s - %s %s %d (%d)\n", + logdatetime, getlogdatetime(), + cep->name, cep->charge, con_secs); + } + } + + /* set the B-channel inactive */ + + if((set_channel_idle(cep->isdncontrollerused, cep->isdnchannelused)) == ERROR) + log(LL_ERR, "msg_disconnect_ind: set_channel_idle failed!"); + + incr_free_channels(cep->isdncontrollerused); + + cep->connect_time = 0; + + next_state(cep, EV_MDI); +} + +/*---------------------------------------------------------------------------* + * handle incoming DIALOUT message + *---------------------------------------------------------------------------*/ +void +msg_dialout(msg_dialout_ind_t *mp) +{ + cfg_entry_t *cep; + + DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: dial req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit))); + + if((cep = find_by_device_for_dialout(mp->driver, mp->driver_unit)) == NULL) + { + DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: config entry reserved or no match"))); + return; + } + + if(cep->inout == DIR_INONLY) + { + dialresponse(cep, DSTAT_INONLY); + return; + } + + if((cep->cdid = get_cdid()) == 0) + { + DBGL(DL_DRVR, (log(LL_DBG, "msg_dialout: get_cdid() returned 0!"))); + return; + } + + cep->charge = 0; + cep->last_charge = 0; + + next_state(cep, EV_MDO); +} + +/*---------------------------------------------------------------------------* + * handle incoming DRVRDISC_REQ message + *---------------------------------------------------------------------------*/ +void +msg_drvrdisc_req(msg_drvrdisc_req_t *mp) +{ + cfg_entry_t *cep; + + DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: req from %s, unit %d", bdrivername(mp->driver), mp->driver_unit))); + + if((cep = get_cep_by_driver(mp->driver, mp->driver_unit)) == NULL) + { + DBGL(DL_DRVR, (log(LL_DBG, "msg_drvrdisc_req: config entry not found"))); + return; + } + next_state(cep, EV_DRQ); +} + +/*---------------------------------------------------------------------------* + * handle incoming ACCOUNTING message + *---------------------------------------------------------------------------*/ +void +msg_accounting(msg_accounting_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = find_active_entry_by_driver(mp->driver, mp->driver_unit)) == NULL) + { + log(LL_WRN, "msg_accounting: no config entry found!"); + return; + } + + cep->inbytes = mp->inbytes; + cep->iinbytes = mp->iinbytes; + cep->outbytes = mp->outbytes; + cep->ioutbytes = mp->ioutbytes; + cep->inbps = mp->inbps; + cep->outbps = mp->outbps; + + if(mp->accttype == ACCT_DURING) + { +#ifdef USE_CURSES + if(do_fullscreen) + display_acct(cep); +#endif +#ifdef NOTDEF + else + DBGL(DL_DRVR, (log(LL_DBG, "msg_accounting: %s%d, ioutb=%d, iinb=%d, outb=%d, inb=%d, outbps=%d, inbps=%d", + bdrivername(mp->driver), mp->driver_unit, + mp->ioutbytes, mp->iinbytes, + mp->outbytes, mp->inbytes, + mp->outbps, mp->inbps))); +#endif + } +} + +/*---------------------------------------------------------------------------* + * handle incoming CHARGING message + *---------------------------------------------------------------------------*/ +void +msg_charging_ind(msg_charging_ind_t *mp) +{ + static char *cttab[] = { + "invalid", + "AOCD", + "AOCE", + "estimated" }; + + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_charging_ind: cdid not found"); + return; + } + + if(mp->units_type < CHARGE_INVALID || mp->units_type > CHARGE_CALC) + { + log(LL_ERR, "msg_charging: units_type %d out of range!", mp->units_type); + do_exit(1); + } + + DBGL(DL_DRVR, (log(LL_DBG, "msg_charging: %d unit(s) (%s)", + mp->units, cttab[mp->units_type]))); + + switch(mp->units_type) + { + case CHARGE_AOCD: + cep->charge = mp->units; + + if((cep->unitlengthsrc == ULSRC_DYN) && + (cep->charge != cep->last_charge)) + { + cep->last_charge = cep->charge; + handle_charge(cep); + } + break; + + case CHARGE_AOCE: + cep->charge = mp->units; + break; + + case CHARGE_CALC: + cep->charge = mp->units; +#ifdef USE_CURSES + if(do_fullscreen) + display_ccharge(cep, mp->units); +#endif +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor && accepted) + monitor_evnt_charge(cep, mp->units, 1); +#endif + break; + } +} + +/*---------------------------------------------------------------------------* + * handle incoming IDLE_TIMEOUT_IND message + *---------------------------------------------------------------------------*/ +void +msg_idle_timeout_ind(msg_idle_timeout_ind_t *mp) +{ + cfg_entry_t *cep; + + if((cep = get_cep_by_cdid(mp->header.cdid)) == NULL) + { + log(LL_WRN, "msg_idle_timeout_ind: cdid not found!"); + return; + } + + cep->local_disconnect = DISCON_LOC; + + DBGL(DL_DRVR, (log(LL_DBG, "msg_idle_timeout_ind: idletimeout, kernel sent disconnect!"))); + + check_and_kill(cep); +} + +/*---------------------------------------------------------------------------* + * get a cdid from kernel + *---------------------------------------------------------------------------*/ +int +get_cdid(void) +{ + msg_cdid_req_t mcr; + + mcr.cdid = 0; + + if((ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0) + { + log(LL_ERR, "get_cdid: ioctl I4B_CDID_REQ failed: %s", strerror(errno)); + do_exit(1); + } + + return(mcr.cdid); +} + +/*---------------------------------------------------------------------------* + * send message "connect request" to kernel + *---------------------------------------------------------------------------*/ +int +sendm_connect_req(cfg_entry_t *cep) +{ + msg_connect_req_t mcr; + int ret; + + cep->local_disconnect = DISCON_REM; + + cep->unitlength = get_current_rate(cep, 1); + + mcr.cdid = cep->cdid; + + mcr.controller = cep->isdncontrollerused; + mcr.channel = cep->isdnchannelused; + mcr.txdelay = cep->isdntxdelout; + + mcr.bprot = cep->b1protocol; + + mcr.driver = cep->usrdevicename; + mcr.driver_unit = cep->usrdeviceunit; + + mcr.unitlen_time = cep->unitlength; + mcr.idle_time = cep->idle_time_out; + mcr.earlyhup_time = cep->earlyhangup; + + if(cep->unitlengthsrc == ULSRC_DYN) + mcr.unitlen_method = ULEN_METHOD_DYNAMIC; + else + mcr.unitlen_method = ULEN_METHOD_STATIC; + + strcpy(mcr.dst_telno, cep->remote_phone_dialout); + strcpy(mcr.src_telno, cep->local_phone_dialout); + + cep->last_dial_time = time(NULL); + cep->direction = DIR_OUT; + + DBGL(DL_CNST, (log(LL_DBG, "sendm_connect_req: ctrl = %d, chan = %d", cep->isdncontrollerused, cep->isdnchannelused))); + + if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0) + { + log(LL_ERR, "sendm_connect_req: ioctl I4B_CONNECT_REQ failed: %s", strerror(errno)); + do_exit(1); + } + + decr_free_channels(cep->isdncontrollerused); + + log(LL_CHD, "%05d %s dialing out from %s to %s", + cep->cdid, + cep->name, + aliasing ? get_alias(cep->local_phone_dialout) : cep->local_phone_dialout, + aliasing ? get_alias(cep->remote_phone_dialout) : cep->remote_phone_dialout); + + return(ret); +} + +/*---------------------------------------------------------------------------* + * send message "connect response" to kernel + *---------------------------------------------------------------------------*/ +int +sendm_connect_resp(cfg_entry_t *cep, int cdid, int response, int cause) +{ + msg_connect_resp_t mcr; + int ret; + + mcr.cdid = cdid; + + mcr.response = response; + + if(response == SETUP_RESP_REJECT) + { + mcr.cause = cause; + } + else if(response == SETUP_RESP_ACCEPT) + { + cep->direction = DIR_IN; + + mcr.txdelay = cep->isdntxdelin; + + mcr.bprot = cep->b1protocol; + + mcr.driver = cep->usrdevicename; + mcr.driver_unit = cep->usrdeviceunit; + + mcr.max_idle_time = cep->idle_time_in; + } + + if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &mcr)) < 0) + { + log(LL_ERR, "sendm_connect_resp: ioctl I4B_CONNECT_RESP failed: %s", strerror(errno)); + do_exit(1); + } + + DBGL(DL_DRVR, (log(LL_DBG, "sendm_connect_resp: sent CONNECT_RESP"))); + + return(ret); +} + +/*---------------------------------------------------------------------------* + * send message "disconnect request" to kernel + *---------------------------------------------------------------------------*/ +int +sendm_disconnect_req(cfg_entry_t *cep, int cause) +{ + msg_discon_req_t mcr; + int ret; + + mcr.cdid = cep->cdid; + + mcr.cause = cause; + + cep->local_disconnect = DISCON_LOC; + + if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mcr)) < 0) + { + log(LL_ERR, "sendm_disconnect_req: ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno)); + do_exit(1); + } + else + { + DBGL(DL_DRVR, (log(LL_DBG, "sendm_disconnect_req: sent DISCONNECT_REQ"))); + } + return(ret); +} + +/*---------------------------------------------------------------------------* + * send message "alert request" to kernel + *---------------------------------------------------------------------------*/ +int +sendm_alert_req(cfg_entry_t *cep) +{ + msg_alert_req_t mar; + int ret; + + mar.cdid = cep->cdid; + + if((ret = ioctl(isdnfd, I4B_ALERT_REQ, &mar)) < 0) + { + log(LL_ERR, "sendm_alert_req: ioctl I4B_ALERT_REQ failed: %s", strerror(errno)); + do_exit(1); + } + else + { + DBGL(DL_DRVR, (log(LL_DBG, "sendm_alert_req: sent ALERT_REQ"))); + } + return(ret); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/pathnames.h b/usr.sbin/i4b/isdnd/pathnames.h new file mode 100644 index 0000000..75afec9 --- /dev/null +++ b/usr.sbin/i4b/isdnd/pathnames.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - location of files + * ------------------------------ + * + * $Id: pathnames.h,v 1.5 1998/12/05 18:03:30 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:11:17 1998] + * + *---------------------------------------------------------------------------*/ + +#ifndef _PATHNAMES_H_ +#define _PATHNAMES_H_ + +#define I4BDEVICE "/dev/i4b" + +#define ETCPATH "/etc/isdn" +#define CONFIG_FILE_DEF "/etc/isdn/isdnd.rc" +#define RATES_FILE_DEF "/etc/isdn/isdnd.rates" + +#define LIBDIR "/usr/local/lib/isdn" + +#define LOG_FILE_DEF "/var/log/isdnd.log" +#define ACCT_FILE_DEF "/var/log/isdnd.acct" + +#define PIDFILE "/var/run/isdnd.pid" + +#endif /* _PATHNAMES_H_ */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/pcause.c b/usr.sbin/i4b/isdnd/pcause.c new file mode 100644 index 0000000..c782f2c --- /dev/null +++ b/usr.sbin/i4b/isdnd/pcause.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * printing cause values + * --------------------- + * + * $Id: pcause.c,v 1.9 1998/12/05 18:03:31 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:11:31 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +static char *cause_i4b_tab[CAUSE_I4B_MAX+1]; +static char *cause_q850_tab[CAUSE_Q850_MAX]; + +char * +print_i4b_cause(cause_t code) +{ + static char error_message[128]; + + sprintf(error_message, "%d: ", GET_CAUSE_VAL(code)); + + switch(GET_CAUSE_TYPE(code)) + { + case CAUSET_Q850: + strcat(error_message, cause_q850_tab[GET_CAUSE_VAL(code)]); + strcat(error_message, " (Q.850)"); + break; + + case CAUSET_I4B: + if((GET_CAUSE_VAL(code) < CAUSE_I4B_NORMAL) || + (GET_CAUSE_VAL(code) >= CAUSE_I4B_MAX)) + { + SET_CAUSE_VAL(code, CAUSE_I4B_MAX); + } + strcat(error_message, cause_i4b_tab[GET_CAUSE_VAL(code)]); + strcat(error_message, " (I4B)"); + break; + + default: + strcat(error_message, "ERROR: unknown cause type!"); + break; + } + return(error_message); +} + +static char *cause_i4b_tab[CAUSE_I4B_MAX+1] = { + "normal call clearing", + "user busy", + "channel not available", + "incompatible source or destination", + "call rejected", + "destination out of order", + "temporary failure", + "layer 1 error / persistent deactivation", + "ERROR, invalid I4B cause value!" +}; + +static char *cause_q850_tab[CAUSE_Q850_MAX] = { + "Normal D-channel shutdown", + "Unallocated (unassigned) number", + "No route to specified transit network (national use)", + "No route to destination", + "Send special information tone", + "Misdialled trunk prefix (national use)", + "Channel unacceptable", + "Call awarded and being delivered in an established channel", + "Preemption", + "Preemption - circuit reserved for reuse", + +/*10*/ "cause code 10: error, unassigned in Q.850 (03/93)", + "cause code 11: error, unassigned in Q.850 (03/93)", + "cause code 12: error, unassigned in Q.850 (03/93)", + "cause code 13: error, unassigned in Q.850 (03/93)", + "cause code 14: error, unassigned in Q.850 (03/93)", + "cause code 15: error, unassigned in Q.850 (03/93)", + "Normal call clearing", + "User busy", + "No user responding", + "No answer from user (user alerted)", + +/*20*/ "Subscriber absent", + "Call rejected", + "Number changed", + "cause code 23: error, unassigned in Q.850 (03/93)", + "cause code 24: error, unassigned in Q.850 (03/93)", + "cause code 25: error, unassigned in Q.850 (03/93)", + "Non-selected user clearing", + "Destination out of order", + "Invalid number format", + "Facility rejected", + +/*30*/ "Response to STATUS ENQUIRY", + "Normal, unspecified", + "cause code 32: error, unassigned in Q.850 (03/93)", + "cause code 33: error, unassigned in Q.850 (03/93)", + "No circuit / channel available", + "cause code 35: error, unassigned in Q.850 (03/93)", + "cause code 36: error, unassigned in Q.850 (03/93)", + "cause code 37: error, unassigned in Q.850 (03/93)", + "Network out of order", + "Permanent frame mode connection out of service", + +/*40*/ "Permanent frame mode connection operational", + "Temporary failure", + "Switching equipment congestion", + "Access information discarded", + "Requested circuit/channel not available", + "cause code 45: error, unassigned in Q.850 (03/93)", + "Precedence call blocked", + "Resources unavailable, unspecified", + "cause code 48: error, unassigned in Q.850 (03/93)", + "Quality of service unavailable", + +/*50*/ "Requested facility not subscribed", + "cause code 51: error, unassigned in Q.850 (03/93)", + "cause code 52: error, unassigned in Q.850 (03/93)", + "Outgoing calls barred within CUG", + "cause code 54: error, unassigned in Q.850 (03/93)", + "Incoming calls barred within CUG", + "cause code 56: error, unassigned in Q.850 (03/93)", + "Bearer capability not authorized", + "Bearer capability not presently available", + "cause code 59: error, unassigned in Q.850 (03/93)", + +/*60*/ "cause code 60: error, unassigned in Q.850 (03/93)", + "cause code 61: error, unassigned in Q.850 (03/93)", + "Inconsistenciy in designated outg. access info and subscriber class", + "Service or option not available, unspecified", + "cause code 64: error, unassigned in Q.850 (03/93)", + "Bearer capability not implemented", + "Channel type not implemented", + "cause code 67: error, unassigned in Q.850 (03/93)", + "cause code 68: error, unassigned in Q.850 (03/93)", + "Requested facility not implemented", + +/*70*/ "Only restricted digital information bearer capability is available", + "cause code 71: error, unassigned in Q.850 (03/93)", + "cause code 72: error, unassigned in Q.850 (03/93)", + "cause code 73: error, unassigned in Q.850 (03/93)", + "cause code 74: error, unassigned in Q.850 (03/93)", + "cause code 75: error, unassigned in Q.850 (03/93)", + "cause code 76: error, unassigned in Q.850 (03/93)", + "cause code 77: error, unassigned in Q.850 (03/93)", + "cause code 78: error, unassigned in Q.850 (03/93)", + "Service or option not implemented, unspecified", + +/*80*/ "cause code 80: error, unassigned in Q.850 (03/93)", + "Invalid call reference value", + "Identified channel does not exist", + "A suspended call exists, but this call identity does not", + "Call identity in use", + "No call suspended", + "Call having the requested call identity has been cleared", + "User not member of CUG", + "Incompatible destination", + "cause code 89: error, unassigned in Q.850 (03/93)", + +/*90*/ "Non-existent CUG", + "Invalid transit network selection", + "cause code 92: error, unassigned in Q.850 (03/93)", + "cause code 93: error, unassigned in Q.850 (03/93)", + "cause code 94: error, unassigned in Q.850 (03/93)", + "Invalid message, unspecified", + "Mandatory information element is missing", + "Message type non-existent or not implemented", + "Message not compatible with call state or message type non-existent or not implemented", + "Information element/parameter non-existent or not implemented", + +/*100*/ "Invalid information element contents", + "Message not compatible with call state", + "Recovery on timer expiry", + "Parameter non-existent or not implemented, passed on", + "cause code 104: error, unassigned in Q.850 (03/93)", + "cause code 105: error, unassigned in Q.850 (03/93)", + "cause code 106: error, unassigned in Q.850 (03/93)", + "cause code 107: error, unassigned in Q.850 (03/93)", + "cause code 108: error, unassigned in Q.850 (03/93)", + "cause code 109: error, unassigned in Q.850 (03/93)", + +/*110*/ "Message with unrecognized parameter, discarded", + "Protocol error, unspecified", + "cause code 112: error, unassigned in Q.850 (03/93)", + "cause code 113: error, unassigned in Q.850 (03/93)", + "cause code 114: error, unassigned in Q.850 (03/93)", + "cause code 115: error, unassigned in Q.850 (03/93)", + "cause code 116: error, unassigned in Q.850 (03/93)", + "cause code 117: error, unassigned in Q.850 (03/93)", + "cause code 118: error, unassigned in Q.850 (03/93)", + "cause code 119: error, unassigned in Q.850 (03/93)", + +/*120*/ "cause code 120: error, unassigned in Q.850 (03/93)", + "cause code 121: error, unassigned in Q.850 (03/93)", + "cause code 122: error, unassigned in Q.850 (03/93)", + "cause code 123: error, unassigned in Q.850 (03/93)", + "cause code 124: error, unassigned in Q.850 (03/93)", + "cause code 125: error, unassigned in Q.850 (03/93)", + "cause code 126: error, unassigned in Q.850 (03/93)", + "Interworking, unspecified" +}; + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/process.c b/usr.sbin/i4b/isdnd/process.c new file mode 100644 index 0000000..47c9eda --- /dev/null +++ b/usr.sbin/i4b/isdnd/process.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - process handling routines + * -------------------------------------- + * + * $Id: process.c,v 1.6 1998/12/05 18:03:33 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:11:42 1998] + * + * -hm debugging processhandling + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +/*---------------------------------------------------------------------------* + * check if another instance of us is already running + *---------------------------------------------------------------------------*/ +void +check_pid(void) +{ + FILE *fp; + + /* check if another lock-file already exists */ + + if((fp = fopen(PIDFILE, "r")) != NULL) + { + /* lockfile found, check */ + + int oldpid; + + /* read pid from file */ + + if((fscanf(fp, "%d", &oldpid)) != 1) + { + log(LL_ERR, "ERROR, reading pid from lockfile failed, terminating!"); + exit(1); + } + + /* check if process got from file is still alive */ + + if((kill(oldpid, 0)) != 0) + { + /* process does not exist */ + + /* close file */ + + fclose(fp); + + DBGL(DL_PROC, (log(LL_DBG, "removing old lock-file %s", PIDFILE))); + + /* remove file */ + + unlink(PIDFILE); + } + else + { + /* process is still alive */ + + log(LL_ERR, "ERROR, another daemon is already running, pid = %d, terminating!", oldpid); + exit(1); + } + } +} + +/*---------------------------------------------------------------------------* + * establish and init process lock file + *---------------------------------------------------------------------------*/ +void +write_pid(void) +{ + FILE *fp; + + /* write my pid into lock-file */ + + if((fp = fopen(PIDFILE, "w")) == NULL) + { + log(LL_ERR, "ERROR, can't open lockfile for writing, terminating"); + do_exit(1); + } + + if((fprintf(fp, "%d", (int)getpid())) == EOF) + { + log(LL_ERR, "ERROR, can't write pid to lockfile, terminating"); + do_exit(1); + } + + fsync(fileno(fp)); + + fclose(fp); +} + +/*---------------------------------------------------------------------------* + * become a daemon + *---------------------------------------------------------------------------*/ +void +daemonize(void) +{ + int fd; + + switch (fork()) + { + case -1: /* error */ + log(LL_ERR, "ERROR, daemonize/fork: %s", strerror(errno)); + exit(1); + case 0: /* child */ + break; + default: /* parent */ + exit(0); + } + + /* new session / no control tty */ + + if(setsid() == -1) + { + log(LL_ERR, "ERROR, setsid returns: %s", strerror(errno)); + exit(1); + } + + /* go away from mounted dir */ + + chdir("/"); + + /* move i/o to another device ? */ + + if(do_fullscreen && do_rdev) + { + char *tp; + + if((fd = open(rdev, O_RDWR, 0)) != -1) + { + if(!isatty(fd)) + { + log(LL_ERR, "ERROR, device %s is not a tty!", rdev); + exit(1); + } + if((dup2(fd, STDIN_FILENO)) == -1) + { + log(LL_ERR, "ERROR, dup2 stdin: %s", strerror(errno)); + exit(1); + } + if((dup2(fd, STDOUT_FILENO)) == -1) + { + log(LL_ERR, "ERROR, dup2 stdout: %s", strerror(errno)); + exit(1); + } + if((dup2(fd, STDERR_FILENO)) == -1) + { + log(LL_ERR, "ERROR, dup2 stderr: %s", strerror(errno)); + exit(1); + } + } + else + { + log(LL_ERR, "ERROR, cannot open redirected device: %s", strerror(errno)); + exit(1); + } + + if(fd > 2) + { + if((close(fd)) == -1) + { + log(LL_ERR, "ERROR, close in daemonize: %s", strerror(errno)); + exit(1); + } + } + + /* curses output && fork NEEDS controlling tty */ + + if((ioctl(STDIN_FILENO, TIOCSCTTY, (char *)NULL)) < 0) + { + log(LL_ERR, "ERROR, cannot setup tty as controlling terminal: %s", strerror(errno)); + exit(1); + } + + /* in case there is no environment ... */ + + if(((tp = getenv("TERM")) == NULL) || (*tp == '\0')) + { + if(do_ttytype == 0) + { + log(LL_ERR, "ERROR, no environment variable TERM found and -t not specified!"); + exit(1); + } + + if((setenv("TERM", ttype, 1)) != 0) + { + log(LL_ERR, "ERROR, setenv TERM=%s failed: %s", ttype, strerror(errno)); + exit(1); + } + } + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/rates.c b/usr.sbin/i4b/isdnd/rates.c new file mode 100644 index 0000000..c1b1163 --- /dev/null +++ b/usr.sbin/i4b/isdnd/rates.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 1997 Gary Jennejohn. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - charging rates description file handling + * ----------------------------------------------------- + * + * $Id: rates.c,v 1.7 1998/12/05 18:03:34 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:11:55 1998] + * + *---------------------------------------------------------------------------*/ + +static char error[256]; + +#ifdef PARSE_DEBUG_MAIN + +#include <stdio.h> + +#define MAIN + +#define ERROR (-1) + +int main() +{ + int ret; + ret = readrates("/etc/isdn/isdnd.rates"); + if(ret == ERROR) + fprintf(stderr, "readrates returns [%d], [%s]\n", ret, error); + else + fprintf(stderr, "readrates returns [%d]\n", ret); + return(ret); +} + +#endif + +#include "isdnd.h" + +static int getrate(cfg_entry_t *cep); + +/*---------------------------------------------------------------------------* + * parse rates file + *---------------------------------------------------------------------------*/ +int +readrates(char *filename) +{ + char buffer[1024]; + register char *bp; + struct rates *rt, *ort; + int rateindx; + int indx; + int line = 0; + FILE *fp; + int first; +#if DEBUG + int i, j; +#endif + + indx = 0; + rt = ort = NULL; + + if((fp = fopen(filename, "r")) == NULL) + { + sprintf(error, "error open %s: %s", filename, sys_errlist[errno]); + rate_error = error; + return(WARNING); + } + + while((fgets(buffer, MAXPATHLEN, fp)) != NULL) + { + line++; + +/* comments */ + if(buffer[0] == '#' || buffer[0] == ' ' || + buffer[0] == '\t' || buffer[0] == '\n') + { + continue; + } + + bp = &buffer[0]; + + /* rate type */ + + if (*bp == 'r' && *(bp+1) == 'a' && isdigit(*(bp+2))) + { + rateindx = *(bp+2) - '0'; + bp += 3; + + /* eat space delimiter */ + + while(isspace(*bp)) + bp++; + } + else + { + sprintf(error, "rates: invalid rate type %c%c%c in line %d", *bp, *(bp+1), *(bp+2), line); + goto rate_error; + } + if (rateindx >= NRATES) + { + sprintf(error, "rates: invalid rate index %d in line %d", rateindx, line); + goto rate_error; + } + + /* day */ + + if(isdigit(*bp) && *bp >= '0' && *bp <= '6') + { + indx = *bp - '0'; + + DBGL(DL_RATES, (log(LL_DBG, "rates: index = %d", indx))); + } + else + { + sprintf(error, "rates: invalid day digit %c in line %d", *bp, line); + goto rate_error; + } + + if(rates[rateindx][indx] == NULL) + { + rt = (struct rates *)malloc(sizeof (struct rates)); + if (rt == NULL) + { + sprintf(error, "rates: cannot malloc space for rate structure"); + goto rate_error; + } + rt->next = NULL; + rates[rateindx][indx] = rt; + } + + bp++; + + /* eat space delimiter */ + + while(isspace(*bp)) + bp++; + + /* now loop to get the rates entries */ + + first = 1; + + while(*bp && isdigit(*bp)) + { + if(first) + { + first = 0; + } + else + { + ort = rt; + + rt = (struct rates *)malloc(sizeof (struct rates)); + if (rt == NULL) + { + sprintf(error, "rates: cannot malloc space2 for rate structure"); + goto rate_error; + } + ort->next = rt; + rt->next = NULL; + } + + /* start hour */ + + if(isdigit(*bp) && isdigit(*(bp+1))) + { + rt->start_hr = atoi(bp); + bp += 2; + } + else + { + sprintf(error, "rates: start_hr error in line %d", line); + goto rate_error; + } + + /* point */ + + if(*bp == '.') + { + bp++; + } + else + { + sprintf(error, "rates: no '.' after start_hr in line %d", line); + goto rate_error; + } + + /* start minute */ + + if(isdigit(*bp) && isdigit(*(bp+1))) + { + rt->start_min = atoi(bp); + bp += 2; + } + else + { + sprintf(error, "rates: start_min error in line %d", line); + goto rate_error; + } + + /* minus */ + + if(*bp == '-') + { + bp++; + } + else + { + sprintf(error, "rates: no '-' after start_min in line %d", line); + goto rate_error; + } + + /* end hour */ + + if(isdigit(*bp) && isdigit(*(bp+1))) + { + rt->end_hr = atoi(bp); + bp += 2; + } + else + { + sprintf(error, "rates: end_hr error in line %d", line); + goto rate_error; + } + + /* point */ + + if(*bp == '.') + { + bp++; + } + else + { + sprintf(error, "rates: no '.' after end_hr in line %d", line); + goto rate_error; + } + + /* end minute */ + + if(isdigit(*bp) && isdigit(*(bp+1))) + { + rt->end_min = atoi(bp); + bp += 2; + } + else + { + sprintf(error, "rates: end_min error in line %d", line); + goto rate_error; + } + + /* colon */ + + if(*bp == ':') + { + bp++; + } + else + { + sprintf(error, "rates: no ':' after end_min in line %d", line); + goto rate_error; + } + + /* time */ + + if(isdigit(*bp)) + { + rt->rate = atoi(bp); + while(!isspace(*bp)) + bp++; + } + else + { + sprintf(error, "rates: first rate digit error in line %d", line); + goto rate_error; + } + + /* eat space delimiter */ + + while(isspace(*bp)) + bp++; + } + } + +#if DEBUG + if(debug_flags & DL_RATES) + { + for (j = 0; j < NRATES; j++) + { + for (i = 0; i < NDAYS; i++) + { + if (rates [j][i] != NULL) + { + rt = rates [j][i]; + for (; rt; rt = rt->next) + { + log(LL_DBG, "rates: index %d day %d = %d.%d-%d.%d:%d", + j, i, rt->start_hr, rt->start_min, + rt->end_hr,rt->end_min,rt->rate); + } + } + else + { + log(LL_DBG, "rates: NO entry for day %d !!\n", i); + } + } + } + } +#endif + fclose(fp); + return(GOOD); + +rate_error: + fclose(fp); + rate_error = error; + return(ERROR); +} + +#ifndef PARSE_DEBUG_MAIN + +/*---------------------------------------------------------------------------* + * get unit length time from configured source + *---------------------------------------------------------------------------*/ +int +get_current_rate(cfg_entry_t *cep, int logit) +{ + int rt; + + switch(cep->unitlengthsrc) + { + case ULSRC_CMDL: /* specified on commandline */ + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (cmdl)", + cep->cdid, cep->name, unit_length); + return(unit_length); + break; + + case ULSRC_CONF: /* get it from config file */ + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (conf)", + cep->cdid, cep->name, cep->unitlength); + return(cep->unitlength); + + case ULSRC_RATE: /* get it dynamic from ratesfile*/ + if(!got_rate) /* got valid rates struct ?? */ + { + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (no ratefile)", + cep->cdid, cep->name, UNITLENGTH_DEFAULT); + return(UNITLENGTH_DEFAULT); + } + if((cep->ratetype >= NRATES) || + (cep->ratetype == INVALID_RATE)) + { + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (rate out of range)", + cep->cdid, cep->name, UNITLENGTH_DEFAULT); + return(UNITLENGTH_DEFAULT); + } + + if((rt = getrate(cep)) != -1) + { + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (rate)", + cep->cdid, cep->name, rt); + return(rt); + } + + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (ratescan fail)", + cep->cdid, cep->name, UNITLENGTH_DEFAULT); + + return(UNITLENGTH_DEFAULT); + break; + + case ULSRC_DYN: /* dynamically calculated from AOC */ + if((rt = getrate(cep)) != -1) + { + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (aocd, rate)", + cep->cdid, cep->name, rt); + return(rt); + } + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (aocd, default)", + cep->cdid, cep->name, UNITLENGTH_DEFAULT); + + return(UNITLENGTH_DEFAULT); + break; + + default: + if(logit) + log(LL_CHD, "%05d %s rate %d sec/unit (unitlen unknown)", + cep->cdid, cep->name, UNITLENGTH_DEFAULT); + + return(UNITLENGTH_DEFAULT); + break; + } +} + +/*---------------------------------------------------------------------------* + * get the currently active rate + *---------------------------------------------------------------------------*/ +static int +getrate(cfg_entry_t *cep) +{ + struct tm *ptr; + time_t now; + register struct rates *hd; + + if((!got_rate) || + (cep->ratetype >= NRATES) || + (cep->ratetype == INVALID_RATE)) + { + return(-1); + } + + time(&now); /* get current time */ + + ptr = localtime(&now); + + /* walk thru the rates for weekday until rate for current time found */ + + for (hd = rates[cep->ratetype][ptr->tm_wday]; hd; hd = hd->next) + { + /* current time within window ? */ + if((hd->start_hr <= ptr->tm_hour) && + (hd->end_hr > ptr->tm_hour)) + { + DBGL(DL_RATES, (log(LL_DBG, "rate=%d sec/unit (day=%d, beg=%d, end=%d, current=%d)", + hd->rate, + ptr->tm_wday, + hd->start_hr, + hd->end_hr, + ptr->tm_hour))); + + return (hd->rate); + } + } + return(-1); +} + +#endif /* PARSE_DEBUG_MAIN */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/rc_config.c b/usr.sbin/i4b/isdnd/rc_config.c new file mode 100644 index 0000000..884edfa --- /dev/null +++ b/usr.sbin/i4b/isdnd/rc_config.c @@ -0,0 +1,1140 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - config file processing + * ----------------------------------- + * + * $Id: rc_config.c,v 1.35 1998/12/16 13:39:47 hm Exp $ + * + * last edit-date: [Mon Dec 14 13:41:41 1998] + * + *---------------------------------------------------------------------------*/ + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "isdnd.h" +#include "y.tab.h" + +#include "monitor.h" +#include "vararray.h" + +extern int entrycount; +extern int lineno; +extern char *yytext; + +extern FILE *yyin; +extern int yyparse(); + +static void set_config_defaults(void); +static void check_config(void); +static void print_config(void); + +static int nregexpr = 0; +static int nregprog = 0; + +/*---------------------------------------------------------------------------* + * called from main to read and process config file + *---------------------------------------------------------------------------*/ +void +configure(char *filename, int reread) +{ + extern void reset_scanner(FILE *inputfile); + + set_config_defaults(); + + yyin = fopen(filename, "r"); + + if(reread) + { + reset_scanner(yyin); + } + + if (yyin == NULL) + { + log(LL_ERR, "cannot fopen file [%s]", filename); + exit(1); + } + + yyparse(); + + monitor_fixup_rights(); + + check_config(); /* validation and consistency check */ + + fclose(yyin); + + if(do_print) + { + if(config_error_flag) + { + log(LL_ERR, "there were %d error(s) in the configuration file, terminating!", config_error_flag); + exit(1); + } + print_config(); + do_exit(0); + } +} + +/*---------------------------------------------------------------------------* + * yacc error routine + *---------------------------------------------------------------------------*/ +void +yyerror(const char *msg) +{ + log(LL_ERR, "configuration error: %s at line %d, token \"%s\"", msg, lineno+1, yytext); + config_error_flag++; +} + +/*---------------------------------------------------------------------------* + * fill all config entries with default values + *---------------------------------------------------------------------------*/ +static void +set_config_defaults(void) +{ + cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */ + int i; + + /* system section cleanup */ + + nregprog = nregexpr = 0; + + rt_prio = RTPRIO_NOTUSED; + + /* clean regular expression table */ + + for(i=0; i < MAX_RE; i++) + { + if(rarr[i].re_expr) + free(rarr[i].re_expr); + rarr[i].re_expr = NULL; + + if(rarr[i].re_prog) + free(rarr[i].re_prog); + rarr[i].re_prog = NULL; + + rarr[i].re_flg = 0; + } + + /* entry section cleanup */ + + for(i=0; i < CFG_ENTRY_MAX; i++, cep++) + { + bzero(cep, sizeof(cfg_entry_t)); + + /* ====== filled in at startup configuration, then static */ + + sprintf(cep->name, "ENTRY%d", i); + + cep->isdncontroller = INVALID; + cep->isdnchannel = CHAN_ANY; + + cep->usrdevicename = INVALID; + cep->usrdeviceunit = INVALID; + + cep->remote_numbers_handling = RNH_LAST; + + cep->dialin_reaction = REACT_IGNORE; + + cep->b1protocol = BPROT_NONE; + + cep->unitlength = UNITLENGTH_DEFAULT; + + cep->earlyhangup = EARLYHANGUP_DEFAULT; + + cep->ratetype = INVALID_RATE; + + cep->unitlengthsrc = ULSRC_NONE; + + cep->answerprog = ANSWERPROG_DEF; + + cep->callbackwait = CALLBACKWAIT_MIN; + + cep->calledbackwait = CALLEDBACKWAIT_MIN; + + cep->dialretries = DIALRETRIES_DEF; + + cep->recoverytime = RECOVERYTIME_MIN; + + cep->dialouttype = DIALOUT_NORMAL; + + cep->inout = DIR_INOUT; + + /* ======== filled in after start, then dynamic */ + + cep->cdid = CDID_UNUSED; + + cep->state = ST_IDLE; + + cep->aoc_valid = AOC_INVALID; + } +} + +/*---------------------------------------------------------------------------* + * extract values from config and fill table + *---------------------------------------------------------------------------*/ +void +cfg_setval(int keyword) +{ + int i; + + switch(keyword) + { + case ACCTALL: + acct_all = yylval.booln; + log(LL_DBG, "system: acctall = %d", yylval.booln); + break; + + case ACCTFILE: + strcpy(acctfile, yylval.str); + log(LL_DBG, "system: acctfile = %s", yylval.str); + break; + + case ALERT: + if(yylval.num < MINALERT) + { + yylval.num = MINALERT; + log(LL_DBG, "entry %d: alert < %d, min = %d", entrycount, MINALERT, yylval.num); + } + else if(yylval.num > MAXALERT) + { + yylval.num = MAXALERT; + log(LL_DBG, "entry %d: alert > %d, min = %d", entrycount, MAXALERT, yylval.num); + } + + log(LL_DBG, "entry %d: alert = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].alert = yylval.num; + break; + + case ALIASING: + log(LL_DBG, "system: aliasing = %d", yylval.booln); + aliasing = yylval.booln; + break; + + case ALIASFNAME: + strcpy(aliasfile, yylval.str); + log(LL_DBG, "system: aliasfile = %s", yylval.str); + break; + + case ANSWERPROG: + if((cfg_entry_tab[entrycount].answerprog = malloc(strlen(yylval.str)+1)) == NULL) + { + log(LL_ERR, "entry %d: answerstring, malloc failed!", entrycount); + do_exit(1); + } + strcpy(cfg_entry_tab[entrycount].answerprog, yylval.str); + log(LL_DBG, "entry %d: answerprog = %s", entrycount, yylval.str); + break; + + case B1PROTOCOL: + log(LL_DBG, "entry %d: b1protocol = %s", entrycount, yylval.str); + if(!(strcmp(yylval.str, "raw"))) + cfg_entry_tab[entrycount].b1protocol = BPROT_NONE; + else if(!(strcmp(yylval.str, "hdlc"))) + cfg_entry_tab[entrycount].b1protocol = BPROT_RHDLC; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"b1protocol\" at line %d!", lineno); + config_error_flag++; + } + break; + + case CALLBACKWAIT: + if(yylval.num < CALLBACKWAIT_MIN) + { + yylval.num = CALLBACKWAIT_MIN; + log(LL_DBG, "entry %d: callbackwait < %d, min = %d", entrycount, CALLBACKWAIT_MIN, yylval.num); + } + + log(LL_DBG, "entry %d: callbackwait = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].callbackwait = yylval.num; + break; + + case CALLEDBACKWAIT: + if(yylval.num < CALLEDBACKWAIT_MIN) + { + yylval.num = CALLEDBACKWAIT_MIN; + log(LL_DBG, "entry %d: calledbackwait < %d, min = %d", entrycount, CALLEDBACKWAIT_MIN, yylval.num); + } + + log(LL_DBG, "entry %d: calledbackwait = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].calledbackwait = yylval.num; + break; + + case CONNECTPROG: + if((cfg_entry_tab[entrycount].connectprog = malloc(strlen(yylval.str)+1)) == NULL) + { + log(LL_ERR, "entry %d: connectprog, malloc failed!", entrycount); + do_exit(1); + } + strcpy(cfg_entry_tab[entrycount].connectprog, yylval.str); + log(LL_DBG, "entry %d: connectprog = %s", entrycount, yylval.str); + break; + + case DIALOUTTYPE: + log(LL_DBG, "entry %d: dialouttype = %s", entrycount, yylval.str); + if(!(strcmp(yylval.str, "normal"))) + cfg_entry_tab[entrycount].dialouttype = DIALOUT_NORMAL; + else if(!(strcmp(yylval.str, "calledback"))) + cfg_entry_tab[entrycount].dialouttype = DIALOUT_CALLEDBACK; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialout-type\" at line %d!", lineno); + config_error_flag++; + } + break; + + case DIALRETRIES: + log(LL_DBG, "entry %d: dialretries = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].dialretries = yylval.num; + break; + + case DIALRANDINCR: + log(LL_DBG, "entry %d: dialrandincr = %d", entrycount, yylval.booln); + cfg_entry_tab[entrycount].dialrandincr = yylval.booln; + break; + + case DIRECTION: + log(LL_DBG, "entry %d: direction = %s", entrycount, yylval.str); + + if(!(strcmp(yylval.str, "inout"))) + cfg_entry_tab[entrycount].inout = DIR_INOUT; + else if(!(strcmp(yylval.str, "in"))) + cfg_entry_tab[entrycount].inout = DIR_INONLY; + else if(!(strcmp(yylval.str, "out"))) + cfg_entry_tab[entrycount].inout = DIR_OUTONLY; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"direction\" at line %d!", lineno); + config_error_flag++; + } + break; + + case DISCONNECTPROG: + if((cfg_entry_tab[entrycount].disconnectprog = malloc(strlen(yylval.str)+1)) == NULL) + { + log(LL_ERR, "entry %d: disconnectprog, malloc failed!", entrycount); + do_exit(1); + } + strcpy(cfg_entry_tab[entrycount].disconnectprog, yylval.str); + log(LL_DBG, "entry %d: disconnectprog = %s", entrycount, yylval.str); + break; + + case DOWNTRIES: + if(yylval.num > DOWN_TRIES_MAX) + yylval.num = DOWN_TRIES_MAX; + else if(yylval.num < DOWN_TRIES_MIN) + yylval.num = DOWN_TRIES_MIN; + + log(LL_DBG, "entry %d: downtries = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].downtries = yylval.num; + break; + + case DOWNTIME: + if(yylval.num > DOWN_TIME_MAX) + yylval.num = DOWN_TIME_MAX; + else if(yylval.num < DOWN_TIME_MIN) + yylval.num = DOWN_TIME_MIN; + + log(LL_DBG, "entry %d: downtime = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].downtime = yylval.num; + break; + + case EARLYHANGUP: + log(LL_DBG, "entry %d: earlyhangup = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].earlyhangup = yylval.num; + break; + + case IDLETIME_IN: + log(LL_DBG, "entry %d: idle_time_in = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].idle_time_in = yylval.num; + break; + + case IDLETIME_OUT: + log(LL_DBG, "entry %d: idle_time_out = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].idle_time_out = yylval.num; + break; + + case ISDNCONTROLLER: + cfg_entry_tab[entrycount].isdncontroller = yylval.num; + log(LL_DBG, "entry %d: isdncontroller = %d", entrycount, yylval.num); + break; + + case ISDNCHANNEL: + switch(yylval.num) + { + case 0: + case -1: + cfg_entry_tab[entrycount].isdnchannel = CHAN_ANY; + log(LL_DBG, "entry %d: isdnchannel = any", entrycount); + break; + case 1: + cfg_entry_tab[entrycount].isdnchannel = CHAN_B1; + log(LL_DBG, "entry %d: isdnchannel = one", entrycount); + break; + case 2: + cfg_entry_tab[entrycount].isdnchannel = CHAN_B2; + log(LL_DBG, "entry %d: isdnchannel = two", entrycount); + break; + default: + log(LL_DBG, "entry %d: isdnchannel value out of range", entrycount); + config_error_flag++; + break; + } + break; + + case ISDNTIME: + log(LL_DBG, "system: isdntime = %d", yylval.booln); + isdntime = yylval.booln; + break; + + case ISDNTXDELIN: + cfg_entry_tab[entrycount].isdntxdelin = yylval.num; + log(LL_DBG, "entry %d: isdntxdel-incoming = %d", entrycount, yylval.num); + break; + + case ISDNTXDELOUT: + cfg_entry_tab[entrycount].isdntxdelout = yylval.num; + log(LL_DBG, "entry %d: isdntxdel-outgoing = %d", entrycount, yylval.num); + break; + + case LOCAL_PHONE_DIALOUT: + log(LL_DBG, "entry %d: local_phone_dialout = %s", entrycount, yylval.str); + strcpy(cfg_entry_tab[entrycount].local_phone_dialout, yylval.str); + break; + + case LOCAL_PHONE_INCOMING: + log(LL_DBG, "entry %d: local_phone_incoming = %s", entrycount, yylval.str); + strcpy(cfg_entry_tab[entrycount].local_phone_incoming, yylval.str); + break; + + case MONITORPORT: + monitorport = yylval.num; + log(LL_DBG, "system: monitorport = %d", yylval.num); + break; + + case MONITORSW: + if (yylval.booln && inhibit_monitor) { + do_monitor = 0; + log(LL_DBG, "system: monitor-enable overriden by command line flag"); + } else { + do_monitor = yylval.booln; + log(LL_DBG, "system: monitor-enable = %d", yylval.booln); + } + break; + + case NAME: + log(LL_DBG, "entry %d: name = %s", entrycount, yylval.str); + strcpy(cfg_entry_tab[entrycount].name, yylval.str); + break; + + case REACTION: + log(LL_DBG, "entry %d: dialin_reaction = %s", entrycount, yylval.str); + if(!(strcmp(yylval.str, "accept"))) + cfg_entry_tab[entrycount].dialin_reaction = REACT_ACCEPT; + else if(!(strcmp(yylval.str, "reject"))) + cfg_entry_tab[entrycount].dialin_reaction = REACT_REJECT; + else if(!(strcmp(yylval.str, "ignore"))) + cfg_entry_tab[entrycount].dialin_reaction = REACT_IGNORE; + else if(!(strcmp(yylval.str, "answer"))) + cfg_entry_tab[entrycount].dialin_reaction = REACT_ANSWER; + else if(!(strcmp(yylval.str, "callback"))) + cfg_entry_tab[entrycount].dialin_reaction = REACT_CALLBACK; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"dialin_reaction\" at line %d!", lineno); + config_error_flag++; + } + break; + + case REMOTE_PHONE_DIALOUT: + if(cfg_entry_tab[entrycount].remote_numbers_count >= MAXRNUMBERS) + { + log(LL_ERR, "ERROR parsing config file: too many remote numbers at line %d!", lineno); + config_error_flag++; + break; + } + + log(LL_DBG, "entry %d: remote_phone_dialout #%d = %s", + entrycount, cfg_entry_tab[entrycount].remote_numbers_count, yylval.str); + + strcpy(cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].number, yylval.str); + cfg_entry_tab[entrycount].remote_numbers[cfg_entry_tab[entrycount].remote_numbers_count].flag = 0; + + cfg_entry_tab[entrycount].remote_numbers_count++; + + break; + + case REMOTE_NUMBERS_HANDLING: + log(LL_DBG, "entry %d: remdial_handling = %s", entrycount, yylval.str); + if(!(strcmp(yylval.str, "next"))) + cfg_entry_tab[entrycount].remote_numbers_handling = RNH_NEXT; + else if(!(strcmp(yylval.str, "last"))) + cfg_entry_tab[entrycount].remote_numbers_handling = RNH_LAST; + else if(!(strcmp(yylval.str, "first"))) + cfg_entry_tab[entrycount].remote_numbers_handling = RNH_FIRST; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"remdial_handling\" at line %d!", lineno); + config_error_flag++; + } + break; + + case REMOTE_PHONE_INCOMING: + { + int n; + n = cfg_entry_tab[entrycount].incoming_numbers_count; + if (n >= MAX_INCOMING) + { + log(LL_ERR, "ERROR parsing config file: too many \"remote_phone_incoming\" entries at line %d!", lineno); + config_error_flag++; + break; + } + log(LL_DBG, "entry %d: remote_phone_incoming #%d = %s", entrycount, n, yylval.str); + strcpy(cfg_entry_tab[entrycount].remote_phone_incoming[n].number, yylval.str); + cfg_entry_tab[entrycount].incoming_numbers_count++; + } + break; + + case RATESFILE: + strcpy(ratesfile, yylval.str); + log(LL_DBG, "system: ratesfile = %s", yylval.str); + break; + + case RATETYPE: + log(LL_DBG, "entry %d: ratetype = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].ratetype = yylval.num; + break; + + case RECOVERYTIME: + if(yylval.num < RECOVERYTIME_MIN) + { + yylval.num = RECOVERYTIME_MIN; + log(LL_DBG, "entry %d: recoverytime < %d, min = %d", entrycount, RECOVERYTIME_MIN, yylval.num); + } + + log(LL_DBG, "entry %d: recoverytime = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].recoverytime = yylval.num; + break; + + case REGEXPR: + if(nregexpr >= MAX_RE) + { + log(LL_DBG, "system: regexpr #%d >= MAX_RE", nregexpr); + config_error_flag++; + break; + } + + if((i = regcomp(&(rarr[nregexpr].re), yylval.str, REG_EXTENDED|REG_NOSUB)) != 0) + { + char buf[256]; + regerror(i, &(rarr[nregexpr].re), buf, sizeof(buf)); + log(LL_DBG, "system: regcomp error for %s: [%s]", yylval.str, buf); + config_error_flag++; + break; + } + else + { + if((rarr[nregexpr].re_expr = malloc(strlen(yylval.str)+1)) == NULL) + { + log(LL_DBG, "system: regexpr malloc error error for %s", yylval.str); + config_error_flag++; + break; + } + strcpy(rarr[nregexpr].re_expr, yylval.str); + + log(LL_DBG, "system: regexpr %s stored into slot %d", yylval.str, nregexpr); + + if(rarr[nregexpr].re_prog != NULL) + rarr[nregexpr].re_flg = 1; + + nregexpr++; + + } + break; + + case REGPROG: + if(nregprog >= MAX_RE) + { + log(LL_DBG, "system: regprog #%d >= MAX_RE", nregprog); + config_error_flag++; + break; + } + if((rarr[nregprog].re_prog = malloc(strlen(yylval.str)+1)) == NULL) + { + log(LL_DBG, "system: regprog malloc error error for %s", yylval.str); + config_error_flag++; + break; + } + strcpy(rarr[nregprog].re_prog, yylval.str); + + log(LL_DBG, "system: regprog %s stored into slot %d", yylval.str, nregprog); + + if(rarr[nregprog].re_expr != NULL) + rarr[nregprog].re_flg = 1; + + nregprog++; + break; + + case RTPRIO: +#ifdef USE_RTPRIO + rt_prio = yylval.num; + if(rt_prio < RTP_PRIO_MIN || rt_prio > RTP_PRIO_MAX) + { + config_error_flag++; + log(LL_DBG, "system: error, rtprio (%d) out of range!", yylval.num); + } + else + { + log(LL_DBG, "system: rtprio = %d", yylval.num); + } +#else + rt_prio = RTPRIO_NOTUSED; +#endif + break; + + case UNITLENGTH: + log(LL_DBG, "entry %d: unitlength = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].unitlength = yylval.num; + break; + + case UNITLENGTHSRC: + log(LL_DBG, "entry %d: unitlengthsrc = %s", entrycount, yylval.str); + if(!(strcmp(yylval.str, "none"))) + cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_NONE; + else if(!(strcmp(yylval.str, "cmdl"))) + cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CMDL; + else if(!(strcmp(yylval.str, "conf"))) + cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_CONF; + else if(!(strcmp(yylval.str, "rate"))) + cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_RATE; + else if(!(strcmp(yylval.str, "aocd"))) + cfg_entry_tab[entrycount].unitlengthsrc = ULSRC_DYN; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"unitlengthsrc\" at line %d!", lineno); + config_error_flag++; + } + break; + + case USRDEVICENAME: + log(LL_DBG, "entry %d: usrdevicename = %s", entrycount, yylval.str); + if(!strcmp(yylval.str, "rbch")) + cfg_entry_tab[entrycount].usrdevicename = BDRV_RBCH; + else if(!strcmp(yylval.str, "tel")) + cfg_entry_tab[entrycount].usrdevicename = BDRV_TEL; + else if(!strcmp(yylval.str, "ipr")) + cfg_entry_tab[entrycount].usrdevicename = BDRV_IPR; + else if(!strcmp(yylval.str, "isp")) + cfg_entry_tab[entrycount].usrdevicename = BDRV_ISPPP; + else + { + log(LL_ERR, "ERROR parsing config file: unknown parameter for keyword \"usrdevicename\" at line %d!", lineno); + config_error_flag++; + } + break; + + case USRDEVICEUNIT: + log(LL_DBG, "entry %d: usrdeviceunit = %d", entrycount, yylval.num); + cfg_entry_tab[entrycount].usrdeviceunit = yylval.num; + break; + + case USEACCTFILE: + useacctfile = yylval.booln; + log(LL_DBG, "system: useacctfile = %d", yylval.booln); + break; + + case USEDOWN: + log(LL_DBG, "entry %d: usedown = %d", entrycount, yylval.booln); + cfg_entry_tab[entrycount].usedown = yylval.booln; + break; + + default: + log(LL_ERR, "ERROR parsing config file: unknown keyword at line %d!", lineno); + config_error_flag++; + break; + } +} + +/*---------------------------------------------------------------------------* + * configuration validation and consistency check + *---------------------------------------------------------------------------*/ +static void +check_config(void) +{ + cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */ + int i; + int error = 0; + + /* regular expression table */ + + for(i=0; i < MAX_RE; i++) + { + if((rarr[i].re_expr != NULL) && (rarr[i].re_prog == NULL)) + { + log(LL_ERR, "check_config: regular expression %d without program!", i); + error++; + } + if((rarr[i].re_prog != NULL) && (rarr[i].re_expr == NULL)) + { + log(LL_ERR, "check_config: regular expression program %d without expression!", i); + error++; + } + } + + /* entry sections */ + + for(i=0; i <= entrycount; i++, cep++) + { + /* isdn controller number */ + + if((cep->isdncontroller < 0) || (cep->isdncontroller > (ncontroller-1))) + { + log(LL_ERR, "check_config: isdncontroller out of range in entry %d!", i); + error++; + } + + /* numbers used for dialout */ + + if((cep->inout != DIR_INONLY) && (cep->dialin_reaction != REACT_ANSWER)) + { + if(cep->remote_numbers_count == 0) + { + log(LL_ERR, "check_config: remote-phone-dialout not set in entry %d!", i); + error++; + } + if(strlen(cep->local_phone_dialout) == 0) + { + log(LL_ERR, "check_config: local-phone-dialout not set in entry %d!", i); + error++; + } + } + + /* numbers used for incoming calls */ + + if(cep->inout != DIR_OUTONLY) + { + if(strlen(cep->local_phone_incoming) == 0) + { + log(LL_ERR, "check_config: local-phone-incoming not set in entry %d!", i); + error++; + } + if(cep->incoming_numbers_count == 0) + { + log(LL_ERR, "check_config: remote-phone-incoming not set in entry %d!", i); + error++; + } + } + + if((cep->dialin_reaction == REACT_ANSWER) && (cep->b1protocol != BPROT_NONE)) + { + log(LL_ERR, "check_config: b1protocol not raw for telephony in entry %d!", i); + error++; + } + } + if(error) + { + log(LL_ERR, "check_config: %d error(s) in configuration file, exit!", error); + do_exit(1); + } +} + +/*---------------------------------------------------------------------------* + * print the configuration + *---------------------------------------------------------------------------*/ +static void +print_config(void) +{ +#define PFILE stdout + + cfg_entry_t *cep = &cfg_entry_tab[0]; /* ptr to config entry */ + int i, j; + extern VARA_DECL(struct monitor_rights) rights; + time_t clock; + char mytime[64]; + + time(&clock); + strcpy(mytime, ctime(&clock)); + mytime[strlen(mytime)-1] = '\0'; + + fprintf(PFILE, "#---------------------------------------------------------------------------\n"); + fprintf(PFILE, "# system section (generated %s)\n", mytime); + fprintf(PFILE, "#---------------------------------------------------------------------------\n"); + fprintf(PFILE, "system\n"); + fprintf(PFILE, "useacctfile = %s\n", useacctfile ? "on\t\t\t\t# update accounting information file" : "off\t\t\t\t# don't update accounting information file"); + fprintf(PFILE, "acctall = %s\n", acct_all ? "on\t\t\t\t# put all events into accounting file" : "off\t\t\t\t# put only charged events into accounting file"); + fprintf(PFILE, "acctfile = %s\t\t# accounting information file\n", acctfile); + fprintf(PFILE, "ratesfile = %s\t\t# charging rates database file\n", ratesfile); + +#ifdef USE_RTPRIO + if(rt_prio == RTPRIO_NOTUSED) + fprintf(PFILE, "# rtprio is unused\n"); + else + fprintf(PFILE, "rtprio = %d\t\t\t\t# isdnd runs at realtime priority\n", rt_prio); +#endif + + /* regular expression table */ + + for(i=0; i < MAX_RE; i++) + { + if(rarr[i].re_expr != NULL) + { + fprintf(PFILE, "regexpr = \"%s\"\t\t# scan logfile for this expression\n", rarr[i].re_expr); + } + if(rarr[i].re_prog != NULL) + { + fprintf(PFILE, "regprog = %s\t\t# program to run when expression is matched\n", rarr[i].re_prog); + } + } + +#ifdef I4B_EXTERNAL_MONITOR + + fprintf(PFILE, "monitor-allowed = %s\n", do_monitor ? "on\t\t\t\t# remote isdnd monitoring allowed" : "off\t\t\t\t# remote isdnd monitoring disabled"); + fprintf(PFILE, "monitor-port = %d\t\t\t\t# TCP/IP port number used for remote monitoring\n", monitorport); + + if(VARA_NUM(rights)) + { + char *s = "error\n"; + char b[512]; + + VARA_FOREACH(rights, i) + { + if(VARA_AT(rights, i).local) + { + fprintf(PFILE, "monitor = \"%s\"\t\t# local socket name for monitoring\n", VARA_AT(rights, i).name); + } + else + { + struct in_addr ia; + ia.s_addr = ntohl(VARA_AT(rights, i).net); + + switch(VARA_AT(rights, i).mask) + { + case 0xffffffff: + s = "32"; + break; + case 0xfffffffe: + s = "31"; + break; + case 0xfffffffc: + s = "30"; + break; + case 0xfffffff8: + s = "29"; + break; + case 0xfffffff0: + s = "28"; + break; + case 0xffffffe0: + s = "27"; + break; + case 0xffffffc0: + s = "26"; + break; + case 0xffffff80: + s = "25"; + break; + case 0xffffff00: + s = "24"; + break; + case 0xfffffe00: + s = "23"; + break; + case 0xfffffc00: + s = "22"; + break; + case 0xfffff800: + s = "21"; + break; + case 0xfffff000: + s = "20"; + break; + case 0xffffe000: + s = "19"; + break; + case 0xffffc000: + s = "18"; + break; + case 0xffff8000: + s = "17"; + break; + case 0xffff0000: + s = "16"; + break; + case 0xfffe0000: + s = "15"; + break; + case 0xfffc0000: + s = "14"; + break; + case 0xfff80000: + s = "13"; + break; + case 0xfff00000: + s = "12"; + break; + case 0xffe00000: + s = "11"; + break; + case 0xffc00000: + s = "10"; + break; + case 0xff800000: + s = "9"; + break; + case 0xff000000: + s = "8"; + break; + case 0xfe000000: + s = "7"; + break; + case 0xfc000000: + s = "6"; + break; + case 0xf8000000: + s = "5"; + break; + case 0xf0000000: + s = "4"; + break; + case 0xe0000000: + s = "3"; + break; + case 0xc0000000: + s = "2"; + break; + case 0x80000000: + s = "1"; + break; + case 0x00000000: + s = "0"; + break; + } + fprintf(PFILE, "monitor = \"%s/%s\"\t\t# host (net/mask) allowed to connect for monitoring\n", inet_ntoa(ia), s); + } + b[0] = '\0'; + + if((VARA_AT(rights, i).rights) & I4B_CA_COMMAND_FULL) + strcat(b, "fullcmd,"); + if((VARA_AT(rights, i).rights) & I4B_CA_COMMAND_RESTRICTED) + strcat(b, "restrictedcmd,"); + if((VARA_AT(rights, i).rights) & I4B_CA_EVNT_CHANSTATE) + strcat(b, "channelstate,"); + if((VARA_AT(rights, i).rights) & I4B_CA_EVNT_CALLIN) + strcat(b, "callin,"); + if((VARA_AT(rights, i).rights) & I4B_CA_EVNT_CALLOUT) + strcat(b, "callout,"); + if((VARA_AT(rights, i).rights) & I4B_CA_EVNT_I4B) + strcat(b, "logevents,"); + + if(b[strlen(b)-1] == ',') + b[strlen(b)-1] = '\0'; + + fprintf(PFILE, "monitor-access = %s\t\t# monitor access rights\n", b); + } + } + +#endif + /* entry sections */ + + for(i=0; i <= entrycount; i++, cep++) + { + fprintf(PFILE, "\n"); + fprintf(PFILE, "#---------------------------------------------------------------------------\n"); + fprintf(PFILE, "# entry section %d\n", i); + fprintf(PFILE, "#---------------------------------------------------------------------------\n"); + fprintf(PFILE, "entry\n"); + + fprintf(PFILE, "name = %s\t\t# name for this entry section\n", cep->name); + + fprintf(PFILE, "isdncontroller = %d\t\t# ISDN card number used for this entry\n", cep->isdncontroller); + fprintf(PFILE, "isdnchannel = "); + switch(cep->isdnchannel) + { + case CHAN_ANY: + fprintf(PFILE, "-1\t\t# any ISDN B-channel may be used\n"); + break; + case CHAN_B1: + fprintf(PFILE, "1\t\t# only ISDN B-channel 1 may be used\n"); + break; + case CHAN_B2: + fprintf(PFILE, "2\t\t# only ISDN B-channel 2 ay be used\n"); + break; + } + + fprintf(PFILE, "usrdevicename = %s\t\t# name of userland ISDN B-channel device\n", bdrivername(cep->usrdevicename)); + fprintf(PFILE, "usrdeviceunit = %d\t\t# unit number of userland ISDN B-channel device\n", cep->usrdeviceunit); + + fprintf(PFILE, "b1protocol = %s\n", cep->b1protocol ? "hdlc\t\t# B-channel layer 1 protocol is HDLC" : "raw\t\t# No B-channel layer 1 protocol used"); + + if(!(cep->usrdevicename == BDRV_TEL)) + { + fprintf(PFILE, "direction = "); + switch(cep->inout) + { + case DIR_INONLY: + fprintf(PFILE, "in\t\t# only incoming connections allowed\n"); + break; + case DIR_OUTONLY: + fprintf(PFILE, "out\t\t# only outgoing connections allowed\n"); + break; + case DIR_INOUT: + fprintf(PFILE, "inout\t\t# incoming and outgoing connections allowed\n"); + break; + } + } + + if(!((cep->usrdevicename == BDRV_TEL) || (cep->inout == DIR_INONLY))) + { + if(cep->remote_numbers_count > 1) + { + for(j=0; j<cep->remote_numbers_count; j++) + fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number %d for dialing out to remote\n", cep->remote_numbers[j].number, j+1); + + fprintf(PFILE, "remdial-handling = "); + + switch(cep->remote_numbers_handling) + { + case RNH_NEXT: + fprintf(PFILE, "next\t\t# use next number after last successfull for new dial\n"); + break; + case RNH_LAST: + fprintf(PFILE, "last\t\t# use last successfull number for new dial\n"); + break; + case RNH_FIRST: + fprintf(PFILE, "first\t\t# always start with first number for new dial\n"); + break; + } + } + else + { + fprintf(PFILE, "remote-phone-dialout = %s\t\t# telephone number for dialing out to remote\n", cep->remote_numbers[0].number); + } + + fprintf(PFILE, "local-phone-dialout = %s\t\t# show this number to remote when dialling out\n", cep->local_phone_dialout); + fprintf(PFILE, "dialout-type = %s\n", cep->dialouttype ? "calledback\t\t# i am called back by remote" : "normal\t\t# i am not called back by remote"); + } + + if(!(cep->inout == DIR_OUTONLY)) + { + int n; + + fprintf(PFILE, "local-phone-incoming = %s\t\t# incoming calls must match this (mine) telephone number\n", cep->local_phone_incoming); + for (n = 0; n < cep->incoming_numbers_count; n++) + fprintf(PFILE, "remote-phone-incoming = %s\t\t# this is a valid remote number to call me\n", + cep->remote_phone_incoming[n].number); + + fprintf(PFILE, "dialin-reaction = "); + switch(cep->dialin_reaction) + { + case REACT_ACCEPT: + fprintf(PFILE, "accept\t\t# i accept a call from remote and connect\n"); + break; + case REACT_REJECT: + fprintf(PFILE, "reject\t\t# i reject the call from remote\n"); + break; + case REACT_IGNORE: + fprintf(PFILE, "ignore\t\t# i ignore the call from remote\n"); + break; + case REACT_ANSWER: + fprintf(PFILE, "answer\t\t# i will start telephone answering when remote calls in\n"); + break; + case REACT_CALLBACK: + fprintf(PFILE, "callback\t\t# when remote calls in, i will hangup and call back\n"); + break; + } + } + + if(!((cep->inout == DIR_INONLY) || (cep->usrdevicename == BDRV_TEL))) + fprintf(PFILE, "idletime-outgoing = %d\t\t# outgoing call idle timeout\n", cep->idle_time_out); + + if(!(cep->inout == DIR_OUTONLY)) + fprintf(PFILE, "idletime-incoming = %d\t\t# incoming call idle timeout\n", cep->idle_time_in); + + if(!(cep->usrdevicename == BDRV_TEL)) + { + fprintf(PFILE, "unitlengthsrc = "); + switch(cep->unitlengthsrc) + { + case ULSRC_NONE: + fprintf(PFILE, "none\t\t# no unit length specified, using default\n"); + break; + case ULSRC_CMDL: + fprintf(PFILE, "cmdl\t\t# using unit length specified on commandline\n"); + break; + case ULSRC_CONF: + fprintf(PFILE, "conf\t\t# using unitlength specified by unitlength-keyword\n"); + fprintf(PFILE, "unitlength = %d\t\t# fixed unitlength\n", cep->unitlength); + break; + case ULSRC_RATE: + fprintf(PFILE, "rate\t\t# using unitlength specified in rate database\n"); + fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype); + break; + case ULSRC_DYN: + fprintf(PFILE, "aocd\t\t# using dynamically calculated unitlength based on AOCD subscription\n"); + fprintf(PFILE, "ratetype = %d\t\t# type of rate from rate database\n", cep->ratetype); + break; + } + + fprintf(PFILE, "earlyhangup = %d\t\t# early hangup safety time\n", cep->earlyhangup); + + } + + if(cep->usrdevicename == BDRV_TEL) + { + fprintf(PFILE, "answerprog = %s\t\t# program used to answer incoming telephone calls\n", cep->answerprog); + fprintf(PFILE, "alert = %d\t\t# number of seconds to wait before accepting a call\n", cep->alert); + } + + if(!(cep->usrdevicename == BDRV_TEL)) + { + if(cep->dialin_reaction == REACT_CALLBACK) + fprintf(PFILE, "callbackwait = %d\t\t# i am waiting this time before calling back remote\n", cep->callbackwait); + + if(cep->dialouttype == DIALOUT_CALLEDBACK) + fprintf(PFILE, "calledbackwait = %d\t\t# i am waiting this time for a call back from remote\n", cep->calledbackwait); + + if(!(cep->inout == DIR_INONLY)) + { + fprintf(PFILE, "dialretries = %d\t\t# number of dialing retries\n", cep->dialretries); + fprintf(PFILE, "recoverytime = %d\t\t# time to wait between dialling retries\n", cep->recoverytime); + fprintf(PFILE, "dialrandincr = %s\t\t# use random dialing time addon\n", cep->dialrandincr ? "on" : "off"); + + fprintf(PFILE, "usedown = %s\n", cep->usedown ? "on\t\t# ISDN device switched off on excessive dial failures" : "off\t\t# no device switchoff on excessive dial failures"); + if(cep->usedown) + { + fprintf(PFILE, "downtries = %d\t\t# number of dialretries failures before switching off\n", cep->downtries); + fprintf(PFILE, "downtime = %d\t\t# time device is switched off\n", cep->downtime); + } + } + } + } + fprintf(PFILE, "\n"); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/rc_parse.y b/usr.sbin/i4b/isdnd/rc_parse.y new file mode 100644 index 0000000..6c1cf14 --- /dev/null +++ b/usr.sbin/i4b/isdnd/rc_parse.y @@ -0,0 +1,388 @@ +/* + * Copyright (c) 1997 Joerg Wunsch. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - runtime configuration parser + * ----------------------------------------- + * + * $Id: rc_parse.y,v 1.15 1998/12/05 18:03:38 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:12:26 1998] + * + *---------------------------------------------------------------------------*/ + +%{ + +/* #define YYDEBUG 1 */ + +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> + +#include "monitor.h" /* monitor access rights bit definitions */ +#include "isdnd.h" + +#ifndef FALSE +# define FALSE 0 +#endif + +#ifndef TRUE +# define TRUE 1 +#endif + +extern void cfg_setval(int keyword); +extern void reset_scanner(FILE *infile); +extern void yyerror(const char *msg); +extern int yylex(); + +extern int lineno; +extern char *yytext; +extern int nentries; + +int saw_system = 0; +int entrycount = -1; + +%} + +%token ACCTALL +%token ACCTFILE +%token ALERT +%token ALIASING +%token ALIASFNAME +%token ANSWERPROG +%token B1PROTOCOL +%token CALLBACKWAIT +%token CALLEDBACKWAIT +%token CONNECTPROG +%token DIALRETRIES +%token DIALRANDINCR +%token DIALOUTTYPE +%token DIRECTION +%token DISCONNECTPROG +%token DOWNTRIES +%token DOWNTIME +%token EARLYHANGUP +%token ENTRY +%token IDLETIME_IN +%token IDLETIME_OUT +%token ISDNCONTROLLER +%token ISDNCHANNEL +%token ISDNTIME +%token ISDNTXDELIN +%token ISDNTXDELOUT +%token LOCAL_PHONE_DIALOUT +%token LOCAL_PHONE_INCOMING +%token MONITORSW +%token MONITORPORT +%token MONITOR +%token MONITORACCESS +%token FULLCMD +%token RESTRICTEDCMD +%token CHANNELSTATE +%token CALLIN +%token CALLOUT +%token LOGEVENTS +%token NAME +%token NO +%token OFF +%token ON +%token RATESFILE +%token RATETYPE +%token REMOTE_NUMBERS_HANDLING +%token REMOTE_PHONE_INCOMING +%token REMOTE_PHONE_DIALOUT +%token REACTION +%token RECOVERYTIME +%token REGEXPR +%token REGPROG +%token RTPRIO +%token SYSTEM +%token UNITLENGTH +%token UNITLENGTHSRC +%token USEACCTFILE +%token USRDEVICENAME +%token USRDEVICEUNIT +%token USEDOWN +%token YES + +%token <str> NUMBERSTR + +%token <str> STRING + +%type <booln> boolean + +%type <num> sysfilekeyword sysnumkeyword sysstrkeyword sysboolkeyword +%type <num> numkeyword strkeyword boolkeyword monrights monright +%type <str> filename + +%union { + int booln; + int num; + char *str; +} + +%% + +config: sections + ; + +sections: possible_nullentries + syssect + entrysects + ; + +possible_nullentries: + /* lambda */ + | possible_nullentries error '\n' + | possible_nullentries nullentry + ; + +nullentry: '\n' + ; + +entrysects: entrysect + | entrysects entrysect + ; + +syssect: SYSTEM sysentries + ; + +sysentries: sysentry + { + saw_system = 1; + monitor_clear_rights(); + } + | sysentries sysentry + ; + +sysentry: sysfileentry + | sysboolentry + | sysnumentry + | sysstrentry + | sysmonitorstart + | sysmonitorrights + | nullentry + | error '\n' + ; + + +sysmonitorstart: + MONITOR '=' STRING '\n' + { + char *err = NULL; + switch (monitor_start_rights($3)) { + case I4BMAR_OK: + break; + case I4BMAR_LENGTH: + err = "local socket name too long: %s"; + break; + case I4BMAR_DUP: + err = "duplicate entry: %s"; + break; + case I4BMAR_CIDR: + err = "invalid CIDR specification: %s"; + break; + case I4BMAR_NOIP: + err = "could not resolve host or net specification: %s"; + break; + } + if (err) { + char msg[1024]; + snprintf(msg, sizeof msg, err, $3); + yyerror(msg); + } + } + ; + +sysmonitorrights: + MONITORACCESS '=' monrights '\n' + { monitor_add_rights($3); } + ; + +monrights: monrights ',' monright { $$ = $1 | $3; } + | monright { $$ = $1; } + ; + +monright: FULLCMD { $$ = I4B_CA_COMMAND_FULL; } + | RESTRICTEDCMD { $$ = I4B_CA_COMMAND_RESTRICTED; } + | CHANNELSTATE { $$ = I4B_CA_EVNT_CHANSTATE; } + | CALLIN { $$ = I4B_CA_EVNT_CALLIN; } + | CALLOUT { $$ = I4B_CA_EVNT_CALLOUT; } + | LOGEVENTS { $$ = I4B_CA_EVNT_I4B; } + ; + +sysfileentry: sysfilekeyword '=' filename '\n' + { + cfg_setval($1); + } + ; + +sysboolentry: sysboolkeyword '=' boolean '\n' + { + yylval.booln = $3; + cfg_setval($1); + } + ; + +sysnumentry: sysnumkeyword '=' NUMBERSTR '\n' + { + yylval.num = atoi($3); + cfg_setval($1); + } + ; + +sysstrentry: sysstrkeyword '=' STRING '\n' + { + cfg_setval($1); + } + | sysstrkeyword '=' NUMBERSTR '\n' + { + cfg_setval($1); + } + ; + +filename: STRING { + if ($1[0] != '/') + { + yyerror("filename doesn't start with a slash"); + YYERROR; + } + $$ = $1; + } + ; + +boolean: NO { $$ = FALSE; } + | OFF { $$ = FALSE; } + | ON { $$ = TRUE; } + | YES { $$ = TRUE; } + ; + +sysfilekeyword: RATESFILE { $$ = RATESFILE; } + | ACCTFILE { $$ = ACCTFILE; } + | ALIASFNAME { $$ = ALIASFNAME; } + ; + +sysboolkeyword: USEACCTFILE { $$ = USEACCTFILE; } + | ALIASING { $$ = ALIASING; } + | ACCTALL { $$ = ACCTALL; } + | ISDNTIME { $$ = ISDNTIME; } + | MONITORSW { $$ = MONITORSW; } + ; + +sysnumkeyword: MONITORPORT { $$ = MONITORPORT; } + | RTPRIO { $$ = RTPRIO; } + ; + +sysstrkeyword: REGEXPR { $$ = REGEXPR; } + | REGPROG { $$ = REGPROG; } + ; + +entrysect: ENTRY + { + entrycount++; + nentries++; + } + entries + ; + +entries: entry + | entries entry + ; + +entry: strentry + | numentry + | boolentry + | nullentry + | error '\n' + ; + +strentry: strkeyword '=' STRING '\n' + { + cfg_setval($1); + } + | strkeyword '=' NUMBERSTR '\n' + { + cfg_setval($1); + } + ; + +boolentry: boolkeyword '=' boolean '\n' + { + yylval.booln = $3; + cfg_setval($1); + } + ; + +numentry: numkeyword '=' NUMBERSTR '\n' + { + yylval.num = atoi($3); + cfg_setval($1); + } + ; + +strkeyword: ANSWERPROG { $$ = ANSWERPROG; } + | B1PROTOCOL { $$ = B1PROTOCOL; } + | CONNECTPROG { $$ = CONNECTPROG; } + | DIALOUTTYPE { $$ = DIALOUTTYPE; } + | DIRECTION { $$ = DIRECTION; } + | DISCONNECTPROG { $$ = DISCONNECTPROG; } + | LOCAL_PHONE_INCOMING { $$ = LOCAL_PHONE_INCOMING; } + | LOCAL_PHONE_DIALOUT { $$ = LOCAL_PHONE_DIALOUT; } + | NAME { $$ = NAME; } + | REACTION { $$ = REACTION; } + | REMOTE_NUMBERS_HANDLING { $$ = REMOTE_NUMBERS_HANDLING; } + | REMOTE_PHONE_INCOMING { $$ = REMOTE_PHONE_INCOMING; } + | REMOTE_PHONE_DIALOUT { $$ = REMOTE_PHONE_DIALOUT; } + | UNITLENGTHSRC { $$ = UNITLENGTHSRC; } + | USRDEVICENAME { $$ = USRDEVICENAME; } + ; + +numkeyword: ALERT { $$ = ALERT; } + | CALLBACKWAIT { $$ = CALLBACKWAIT; } + | CALLEDBACKWAIT { $$ = CALLEDBACKWAIT; } + | DIALRETRIES { $$ = DIALRETRIES; } + | EARLYHANGUP { $$ = EARLYHANGUP; } + | IDLETIME_IN { $$ = IDLETIME_IN; } + | IDLETIME_OUT { $$ = IDLETIME_OUT; } + | ISDNCONTROLLER { $$ = ISDNCONTROLLER; } + | ISDNCHANNEL { $$ = ISDNCHANNEL; } + | ISDNTXDELIN { $$ = ISDNTXDELIN; } + | ISDNTXDELOUT { $$ = ISDNTXDELOUT; } + | RATETYPE { $$ = RATETYPE; } + | RECOVERYTIME { $$ = RECOVERYTIME; } + | UNITLENGTH { $$ = UNITLENGTH; } + | USRDEVICEUNIT { $$ = USRDEVICEUNIT; } + | DOWNTIME { $$ = DOWNTIME; } + | DOWNTRIES { $$ = DOWNTRIES; } + ; + +boolkeyword: DIALRANDINCR { $$ = DIALRANDINCR; } + | USEDOWN { $$ = USEDOWN; } + ; + +%% diff --git a/usr.sbin/i4b/isdnd/rc_scan.l b/usr.sbin/i4b/isdnd/rc_scan.l new file mode 100644 index 0000000..dfca28c --- /dev/null +++ b/usr.sbin/i4b/isdnd/rc_scan.l @@ -0,0 +1,170 @@ +/* + * Copyright (c) 1997 Joerg Wunsch. All rights reserved. + * + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - runtime configuration lexical analyzer + * --------------------------------------------------- + * + * $Id: rc_scan.l,v 1.19 1998/12/18 17:17:57 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:08:25 1998] + * + *---------------------------------------------------------------------------*/ + +%{ + +#include <err.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <sysexits.h> + +#include "y.tab.h" + +int lineno; + +%} + +%option noyywrap +%option nounput + +%% + +#.*$ { /* + * Drop comment. NB: this prevents a hash + * sign from appearing inside a quoted string. + */ + } + +["][^"]*["] { + char *str; + if ((str = malloc(yyleng - 1)) == 0) + errx(EX_OSERR, "Out of virtual memory"); + memcpy(str, yytext + 1, yyleng - 2); + str[yyleng - 2] = 0; + yylval.str = str; + return STRING; + } + +(-*[0-9]+)|\* { + char *str; + char *p = yytext; + int i = 0; + if ((str = malloc(128)) == 0) + errx(EX_OSERR, "Out of virtual memory"); + while(*p == '-' || isdigit(*p) || *p == '*') + str[i++] = *p++; + str[i] = '\0'; + yylval.str = str; + return NUMBERSTR; + } + +acctall { return ACCTALL; } +acctfile { return ACCTFILE; } +alert { return ALERT; } +aliasing { return ALIASING; } +aliasfile { return ALIASFNAME; } +answerprog { return ANSWERPROG; } +b1protocol { return B1PROTOCOL; } +callbackwait { return CALLBACKWAIT; } +calledbackwait { return CALLEDBACKWAIT; } +connectprog { return CONNECTPROG; } +dialin-reaction { return REACTION; } +dialout-type { return DIALOUTTYPE; } +dialrandincr { return DIALRANDINCR; } +dialretries { return DIALRETRIES; } +direction { return DIRECTION; } +disconnectprog { return DISCONNECTPROG; } +downtries { return DOWNTRIES; } +downtime { return DOWNTIME; } +earlyhangup { return EARLYHANGUP; } +entry { return ENTRY; } +idletime-incoming { return IDLETIME_IN; } +idletime-outgoing { return IDLETIME_OUT; } +isdncontroller { return ISDNCONTROLLER; } +isdnchannel { return ISDNCHANNEL; } +isdntime { return ISDNTIME; } +isdntxdel-incoming { return ISDNTXDELIN; } +isdntxdel-outgoing { return ISDNTXDELOUT; } +local-phone-dialout { return LOCAL_PHONE_DIALOUT; } +local-phone-incoming { return LOCAL_PHONE_INCOMING; } +monitor-allowed { return MONITORSW; } +monitor-port { return MONITORPORT; } +monitor { return MONITOR; } +monitor-access { return MONITORACCESS; } +fullcmd { return FULLCMD; } +restrictedcmd { return RESTRICTEDCMD; } +channelstate { return CHANNELSTATE; } +callin { return CALLIN; } +callout { return CALLOUT; } +logevents { return LOGEVENTS; } +name { return NAME; } +no { return NO; } +off { return OFF; } +on { return ON; } +ratesfile { return RATESFILE; } +ratetype { return RATETYPE; } +recoverytime { return RECOVERYTIME; } +regexpr { return REGEXPR; } +regprog { return REGPROG; } +remdial-handling { return REMOTE_NUMBERS_HANDLING; } +remote-phone-dialout { return REMOTE_PHONE_DIALOUT; } +remote-phone-incoming { return REMOTE_PHONE_INCOMING; } +rtprio { return RTPRIO; } +system { return SYSTEM; } +unitlength { return UNITLENGTH; } +unitlengthsrc { return UNITLENGTHSRC; } +useacctfile { return USEACCTFILE; } +usrdevicename { return USRDEVICENAME; } +usrdeviceunit { return USRDEVICEUNIT; } +usedown { return USEDOWN; } +yes { return YES; } + +\n { lineno++; return '\n'; } + +[A-Za-z/.][-A-Za-z0-9_/.]* { + char *str; + if ((str = strdup(yytext)) == 0) + err(EX_OSERR, "Out of virtual memory"); + yylval.str = str; + return STRING; + } + +[ \t] { /* drop white space */ } + +. { return yytext[0]; } + +%% + +void +reset_scanner(FILE *infile) +{ + yyrestart(infile); + lineno = 1; +} diff --git a/usr.sbin/i4b/isdnd/support.c b/usr.sbin/i4b/isdnd/support.c new file mode 100644 index 0000000..77c0841 --- /dev/null +++ b/usr.sbin/i4b/isdnd/support.c @@ -0,0 +1,831 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - misc support routines + * ---------------------------------- + * + * $Id: support.c,v 1.43 1998/12/18 09:47:09 hm Exp $ + * + * last edit-date: [Mon Dec 14 11:17:22 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +#define SRC (aliasing == 0 ? mp->src_telno : src_tela) +#define DST (aliasing == 0 ? mp->dst_telno : dst_tela) + +/*---------------------------------------------------------------------------* + * find an active entry by driver type and driver unit + *---------------------------------------------------------------------------*/ +cfg_entry_t * +find_active_entry_by_driver(int drivertype, int driverunit) +{ + cfg_entry_t *cep = NULL; + int i; + + for(i=0; i < nentries; i++) + { + cep = &cfg_entry_tab[i]; /* ptr to config entry */ + + if(!((cep->usrdevicename == drivertype) && + (cep->usrdeviceunit == driverunit))) + { + continue; + } + + /* found */ + + if(cep->cdid == CDID_UNUSED) + { + DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d, cdid is CDID_UNUSED!", i))); + return(NULL); + } + else if(cep->cdid == CDID_RESERVED) + { + DBGL(DL_MSG, (log(LL_DBG, "find_active_entry_by_driver: entry %d, cdid is CDID_RESERVED!", i))); + return(NULL); + } + return(cep); + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * find entry by drivertype and driverunit and setup for dialing out + *---------------------------------------------------------------------------*/ +cfg_entry_t * +find_by_device_for_dialout(int drivertype, int driverunit) +{ + cfg_entry_t *cep = NULL; + int i; + + for(i=0; i < nentries; i++) + { + cep = &cfg_entry_tab[i]; /* ptr to config entry */ + + /* compare driver type and unit */ + + if(!((cep->usrdevicename == drivertype) && + (cep->usrdeviceunit == driverunit))) + { + continue; + } + + /* found, check if already reserved */ + + if(cep->cdid == CDID_RESERVED) + { + DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid reserved!", i))); + return(NULL); + } + + /* check if this entry is already in use ? */ + + if(cep->cdid != CDID_UNUSED) + { + DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, cdid in use", i))); + return(NULL); + } + + if((setup_dialout(cep)) == GOOD) + { + /* found an entry to be used for calling out */ + + DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: found entry %d!", i))); + return(cep); + } + else + { + DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: entry %d, setup_dialout() failed!", i))); + return(NULL); + } + } + + DBGL(DL_MSG, (log(LL_DBG, "find_by_device_for_dialout: no entry found!"))); + return(NULL); +} + +/*---------------------------------------------------------------------------* + * find entry by drivertype and driverunit and setup for dialing out + *---------------------------------------------------------------------------*/ +int +setup_dialout(cfg_entry_t *cep) +{ + /* check controller operational */ + + if((get_controller_state(cep->isdncontroller)) != CTRL_UP) + { + DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, controller is down", cep->name))); + return(ERROR); + } + + cep->isdncontrollerused = cep->isdncontroller; + + /* check channel available */ + + switch(cep->isdnchannel) + { + case CHAN_B1: + case CHAN_B2: + if((ret_channel_state(cep->isdncontroller, cep->isdnchannel)) != CHAN_IDLE) + { + DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel not free", cep->name))); + return(ERROR); + } + cep->isdnchannelused = cep->isdnchannel; + break; + + case CHAN_ANY: + if(((ret_channel_state(cep->isdncontroller, CHAN_B1)) != CHAN_IDLE) && + ((ret_channel_state(cep->isdncontroller, CHAN_B2)) != CHAN_IDLE)) + { + DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, no channel free", cep->name))); + return(ERROR); + } + cep->isdnchannelused = CHAN_ANY; + break; + + default: + DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s, channel undefined", cep->name))); + return(ERROR); + break; + } + + DBGL(DL_MSG, (log(LL_DBG, "setup_dialout: entry %s ok!", cep->name))); + + /* preset disconnect cause */ + + SET_CAUSE_TYPE(cep->disc_cause, CAUSET_I4B); + SET_CAUSE_VAL(cep->disc_cause, CAUSE_I4B_NORMAL); + + return(GOOD); +} + +/*---------------------------------------------------------------------------* + * find entry by drivertype and driverunit + *---------------------------------------------------------------------------*/ +cfg_entry_t * +get_cep_by_driver(int drivertype, int driverunit) +{ + cfg_entry_t *cep = NULL; + int i; + + for(i=0; i < nentries; i++) + { + cep = &cfg_entry_tab[i]; /* ptr to config entry */ + + if(!((cep->usrdevicename == drivertype) && + (cep->usrdeviceunit == driverunit))) + { + continue; + } + + DBGL(DL_MSG, (log(LL_DBG, "get_cep_by_driver: found entry %d!", i))); + return(cep); + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * find a matching entry for an incoming call + * + * - not found/no match: log output with LL_CHD and return NULL + * - found/match: make entry in free cep, return address + *---------------------------------------------------------------------------*/ +cfg_entry_t * +find_matching_entry_incoming(msg_connect_ind_t *mp) +{ + cfg_entry_t *cep = NULL; + int i; + char *src_tela = "ERROR-src_tela"; + char *dst_tela = "ERROR-dst_tela"; + + for(i=0; i < nentries; i++) + { + int n; + cep = &cfg_entry_tab[i]; /* ptr to config entry */ + + /* check my number */ + + if(strncmp(cep->local_phone_incoming, mp->dst_telno, strlen(cep->local_phone_incoming))) + { + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, myno %s != incomingno %s", i, + cep->local_phone_incoming, mp->dst_telno))); + continue; + } + + /* check all allowed remote number's for this entry */ + + for (n = 0; n < cep->incoming_numbers_count; n++) + { + incoming_number_t *in = &cep->remote_phone_incoming[n]; + if(in->number[0] == '*') + break; + if(strncmp(in->number, mp->src_telno, strlen(in->number))) + { + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, remno %s != incomingfromno %s", i, + in->number, mp->src_telno))); + } + else + break; + } + if (n >= cep->incoming_numbers_count) + continue; + + /* screening indicator XXX */ + + switch(mp->scr_ind) + { + case SCR_NONE: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - no screening indicator", mp->src_telno))); + break; + + case SCR_USR_NOSC: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, not screened", mp->src_telno))); + break; + + case SCR_USR_PASS: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & passed", mp->src_telno))); + break; + + case SCR_USR_FAIL: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening user provided, verified & failed", mp->src_telno))); + break; + + case SCR_NET: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: %s - screening network provided", mp->src_telno))); + break; + + default: + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: ERROR %s - invalid screening indicator!", mp->src_telno))); + break; + } + + /* check b protocol */ + + if(cep->b1protocol != mp->bprot) + { + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, bprot %d != incomingprot %d", i, + cep->b1protocol, mp->bprot))); + continue; + } + + /* is this entry currently in use ? */ + + if(cep->cdid != CDID_UNUSED) + { + if(cep->cdid == CDID_RESERVED) + { + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid is reserved", i))); + } + else if (cep->dialin_reaction == REACT_ACCEPT + && cep->dialouttype == DIALOUT_CALLEDBACK) + { + /* + * We might consider doing this even if this is + * not a calledback config entry - BUT: there are + * severe race conditions and timinig problems + * ex. if both sides run I4B with no callback + * delay - both may shutdown the outgoing call + * and never be able to establish a connection. + * In the called-back case this should not happen. + */ + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, incoming call for callback in progress (cdid %05d)", i, cep->cdid))); + + /* save the current call state, we're going to overwrite it with the + * new incoming state below... */ + cep->saved_call.cdid = cep->cdid; + cep->saved_call.controller = cep->isdncontrollerused; + cep->saved_call.channel = cep->isdnchannelused; + } + else + { + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, cdid in use", i))); + continue; /* yes, next */ + } + } + + /* check controller value ok */ + + if(mp->controller > ncontroller) + { + log(LL_CHD, "%05d %s incoming call with invalid controller %d", + mp->header.cdid, cep->name, mp->controller); + return(NULL); + } + + /* check controller marked up */ + + if((get_controller_state(mp->controller)) != CTRL_UP) + { + log(LL_CHD, "%05d %s incoming call, controller %d DOWN!", + mp->header.cdid, cep->name, mp->controller); + return(NULL); + } + + /* check channel he wants */ + + switch(mp->channel) + { + case CHAN_B1: + case CHAN_B2: + if((ret_channel_state(mp->controller, mp->channel)) != CHAN_IDLE) + { + log(LL_CHD, "%05d %s incoming call, channel %s not free!", + mp->header.cdid, cep->name, mp->channel == CHAN_B1 ? "B1" : "B2"); + return(NULL); + } + break; + + case CHAN_ANY: + if(((ret_channel_state(mp->controller, CHAN_B1)) != CHAN_IDLE) && + ((ret_channel_state(mp->controller, CHAN_B2)) != CHAN_IDLE)) + { + log(LL_CHD, "%05d %s incoming call, no channel free!", + mp->header.cdid, cep->name); + return(NULL); + } + break; + + case CHAN_NO: + log(LL_CHD, "%05d %s incoming call, call waiting (no channel available)!", + mp->header.cdid, cep->name); + return(NULL); + break; + + default: + log(LL_CHD, "%05d %s incoming call, ERROR, channel undefined!", + mp->header.cdid, cep->name); + return(NULL); + break; + } + + /* found a matching entry */ + + cep->cdid = mp->header.cdid; + cep->isdncontrollerused = mp->controller; + cep->isdnchannelused = mp->channel; +/*XXX*/ cep->disc_cause = 0; + + /* cp number to real one used */ + + strcpy(cep->real_phone_incoming, mp->src_telno); + + /* copy display string */ + + strcpy(cep->display, mp->display); + + /* entry currently down ? */ + + if(cep->state == ST_DOWN) + { + msg_updown_ind_t mui; + + /* set interface up */ + + DBGL(DL_MSG, (log(LL_DBG, "find_matching_entry_incoming: entry %d, ", i))); + + mui.driver = cep->usrdevicename; + mui.driver_unit = cep->usrdeviceunit; + mui.updown = SOFT_ENA; + + if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0) + { + log(LL_ERR, "find_matching_entry_incoming: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno)); + do_exit(1); + } + + cep->down_retry_count = 0; + cep->state = ST_IDLE; + } + return(cep); + } + + if(aliasing) + { + src_tela = get_alias(mp->src_telno); + dst_tela = get_alias(mp->dst_telno); + } + log(LL_CHD, /* A number not listed in /etc/isdn/isdnd.rc */ + ( (!aliasing) ? + "%05d <unknown> incoming call from %s to %s" : + /* Probably a phone call, likely from someone + in phone book /etc/isdn/isdntel.alias, so + avoid looking silly by saying "unknown", + & allow more space to print names. + */ + "%05d Call from %s to %s" + ) , + mp->header.cdid, SRC, DST, mp->dst_telno); + + return(NULL); +} + +/*---------------------------------------------------------------------------* + * return address of ACTIVE config entry by controller and channel + *---------------------------------------------------------------------------*/ +cfg_entry_t * +get_cep_by_cc(int ctrlr, int chan) +{ + int i; + + if((chan != CHAN_B1) && (chan != CHAN_B2)) + return(NULL); + + for(i=0; i < nentries; i++) + { + if((cfg_entry_tab[i].cdid != CDID_UNUSED) && + (cfg_entry_tab[i].cdid != CDID_RESERVED) && + (cfg_entry_tab[i].isdnchannelused == chan) && + (cfg_entry_tab[i].isdncontrollerused == ctrlr) && + ((ret_channel_state(ctrlr, chan)) == CHAN_RUN)) + { + return(&cfg_entry_tab[i]); + } + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * return address of config entry identified by cdid + *---------------------------------------------------------------------------*/ +cfg_entry_t * +get_cep_by_cdid(int cdid) +{ + int i; + + for(i=0; i < nentries; i++) + { + if(cfg_entry_tab[i].cdid == cdid + || cfg_entry_tab[i].saved_call.cdid == cdid) + return(&cfg_entry_tab[i]); + } + return(NULL); +} + +/*---------------------------------------------------------------------------* + * get name of a controller + *---------------------------------------------------------------------------*/ +const char * +name_of_controller(int ctrl_type, int card_type) +{ + static char *passive_card[] = { + "Teles S0/8", + "Teles S0/16", + "Teles S0/16.3", + "AVM A1 or Fritz!Card", + "Teles S0/16.3 PnP", + "Creatix S0 PnP", + "USRobotics Sportster ISDN TA", + "Dr. Neuhaus NICCY Go@", + "Sedlbauer win speed", + "Dynalink IS64PH", + "ISDN Master or Blaster", + "AVM PCMCIA Fritz!Card", + "ELSA QuickStep 1000pro/ISA", + "ELSA QuickStep 1000pro/PCI", + "Siemens I-Talk", + "ELSA MicroLink ISDN/MC", + "ELSA MicroLink MCall", + "ITK ix1 micro" + }; + static char *daic_card[] = { + "EICON.Diehl S", + "EICON.Diehl SX/SXn", + "EICON.Diehl SCOM", + "EICON.Diehl QUADRO", + }; + + if (ctrl_type == CTRL_PASSIVE) { + int index = card_type - CARD_TYPEP_8; + if (index >= 0 && index < (sizeof passive_card / sizeof passive_card[0])) + return passive_card[index]; + } else if (ctrl_type == CTRL_DAIC) { + int index = card_type - CARD_TYPEA_DAIC_S; + if (index >= 0 && index < (sizeof daic_card / sizeof daic_card[0] )) + return daic_card[index]; + } + + return "unknown card type"; +} + +/*---------------------------------------------------------------------------* + * init controller state array + *---------------------------------------------------------------------------*/ +void +init_controller(void) +{ + int i; + int max = 1; + msg_ctrl_info_req_t mcir; + + for(i=0; i < max; i++) + { + mcir.controller = i; + + if((ioctl(isdnfd, I4B_CTRL_INFO_REQ, &mcir)) < 0) + { + log(LL_ERR, "init_controller: ioctl I4B_CTRL_INFO_REQ failed: %s", strerror(errno)); + do_exit(1); + } + + if((ncontroller = max = mcir.ncontroller) == 0) + { + log(LL_ERR, "init_controller: no ISDN controller found!"); + do_exit(1); + } + + if(mcir.ctrl_type == -1 || mcir.card_type == -1) + { + log(LL_ERR, "init_controller: ctrl/card is invalid!"); + do_exit(1); + } + + /* init controller tab */ + + if((init_controller_state(i, mcir.ctrl_type, mcir.card_type, mcir.tei)) == ERROR) + { + log(LL_ERR, "init_controller: init_controller_state for controller %d failed", i); + do_exit(1); + } + } + log(LL_DMN, "init_controller: found %d ISDN controller(s)", max); +} + +/*---------------------------------------------------------------------------* + * return b channel driver type name string + *---------------------------------------------------------------------------*/ +char * +bdrivername(int drivertype) +{ + static char *bdtab[] = { + "rbch", + "tel", + "ipr", + "isp" + }; + + if(drivertype >= BDRV_RBCH && drivertype <= BDRV_ISPPP) + return(bdtab[drivertype]); + else + return("unknown"); +} + +/*---------------------------------------------------------------------------* + * process AOCD charging messages + *---------------------------------------------------------------------------*/ +void +handle_charge(cfg_entry_t *cep) +{ + time_t now = time(NULL); + + if(cep->aoc_last == 0) /* no last timestamp yet ? */ + { + cep->aoc_last = now; /* add time stamp */ + } + else if(cep->aoc_now == 0) /* no current timestamp yet ? */ + { + cep->aoc_now = now; /* current timestamp */ + } + else + { + cep->aoc_last = cep->aoc_now; + cep->aoc_now = now; + cep->aoc_diff = cep->aoc_now - cep->aoc_last; + cep->aoc_valid = AOC_VALID; + } + +#ifdef USE_CURSES + if(do_fullscreen) + display_charge(cep); +#endif + +#ifdef I4B_EXTERNAL_MONITOR + if(do_monitor && accepted) + monitor_evnt_charge(cep, cep->charge, 0); +#endif + + if(cep->aoc_valid == AOC_VALID) + { + if(cep->aoc_diff != cep->unitlength) + { + DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length updated %d -> %d secs", cep->unitlength, cep->aoc_diff))); + + cep->unitlength = cep->aoc_diff; + + unitlen_chkupd(cep); + } + else + { +#ifdef NOTDEF + DBGL(DL_MSG, (log(LL_DBG, "handle_charge: AOCD unit length still %d secs", cep->unitlength))); +#endif + } + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +void +unitlen_chkupd(cfg_entry_t *cep) +{ + msg_timeout_upd_t tupd; + +/* XXX check if the values are possible, if not, adjust them */ + + tupd.cdid = cep->cdid; + tupd.unitlen_time = cep->unitlength; + tupd.idle_time = cep->idle_time_out; + tupd.earlyhup_time = cep->earlyhangup; + + if((ioctl(isdnfd, I4B_TIMEOUT_UPD, &tupd)) < 0) + { + log(LL_ERR, "ioctl I4B_TIMEOUT_UPD failed: %s", strerror(errno)); + do_exit(1); + } +} + +/*--------------------------------------------------------------------------* + * this is intended to be called by do_exit and closes down all + * active connections before the daemon exits or is reconfigured. + *--------------------------------------------------------------------------*/ +void +close_allactive(void) +{ + int i, j; + cfg_entry_t *cep = NULL; + + j = 0; + + for (i = 0; i < ncontroller; i++) + { + if((get_controller_state(i)) != CTRL_UP) + continue; + + if((ret_channel_state(i, CHAN_B1)) == CHAN_RUN) + { + if((cep = get_cep_by_cc(i, CHAN_B1)) != NULL) + { +#ifdef USE_CURSES + if(do_fullscreen) + display_disconnect(cep); +#endif +#ifdef I4B_EXTERNAL_MONITOR + monitor_evnt_disconnect(cep); +#endif + next_state(cep, EV_DRQ); + j++; + } + } + + if((ret_channel_state(i, CHAN_B2)) == CHAN_RUN) + { + if((cep = get_cep_by_cc(i, CHAN_B2)) != NULL) + { +#ifdef USE_CURSES + if(do_fullscreen) + display_disconnect(cep); +#endif +#ifdef I4B_EXTERNAL_MONITOR + monitor_evnt_disconnect(cep); +#endif + next_state(cep, EV_DRQ); + j++; + } + } + } + + if(j) + { + log(LL_DMN, "close_allactive: waiting for all connections terminated"); + sleep(5); + } +} + +/*--------------------------------------------------------------------------* + * set an interface up + *--------------------------------------------------------------------------*/ +void +if_up(cfg_entry_t *cep) +{ + msg_updown_ind_t mui; + + /* set interface up */ + + DBGL(DL_MSG, (log(LL_DBG, "if_up: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit))); + + mui.driver = cep->usrdevicename; + mui.driver_unit = cep->usrdeviceunit; + mui.updown = SOFT_ENA; + + if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0) + { + log(LL_ERR, "if_up: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno)); + do_exit(1); + } + cep->down_retry_count = 0; + +#ifdef USE_CURSES + if(do_fullscreen) + display_updown(cep, 1); +#endif +#ifdef I4B_EXTERNAL_MONITOR + monitor_evnt_updown(cep, 1); +#endif + +} + +/*--------------------------------------------------------------------------* + * set an interface down + *--------------------------------------------------------------------------*/ +void +if_down(cfg_entry_t *cep) +{ + msg_updown_ind_t mui; + + /* set interface up */ + + DBGL(DL_MSG, (log(LL_DBG, "if_down: taking %s%d down", bdrivername(cep->usrdevicename), cep->usrdeviceunit))); + + mui.driver = cep->usrdevicename; + mui.driver_unit = cep->usrdeviceunit; + mui.updown = SOFT_DIS; + + if((ioctl(isdnfd, I4B_UPDOWN_IND, &mui)) < 0) + { + log(LL_ERR, "if_down: ioctl I4B_UPDOWN_IND failed: %s", strerror(errno)); + do_exit(1); + } + cep->went_down_time = time(NULL); + cep->down_retry_count = 0; + +#ifdef USE_CURSES + if(do_fullscreen) + display_updown(cep, 0); +#endif +#ifdef I4B_EXTERNAL_MONITOR + monitor_evnt_updown(cep, 0); +#endif + +} + +/*--------------------------------------------------------------------------* + * send a dial response to (an interface in) the kernel + *--------------------------------------------------------------------------*/ +void +dialresponse(cfg_entry_t *cep, int dstat) +{ + msg_dialout_resp_t mdr; + + static char *stattab[] = { + "normal condition", + "temporary failure", + "permanent failure", + "dialout not allowed" + }; + + if(dstat < DSTAT_NONE || dstat > DSTAT_INONLY) + { + log(LL_ERR, "dialresponse: dstat out of range %d!", dstat); + return; + } + + mdr.driver = cep->usrdevicename; + mdr.driver_unit = cep->usrdeviceunit; + mdr.stat = dstat; + + if((ioctl(isdnfd, I4B_DIALOUT_RESP, &mdr)) < 0) + { + log(LL_ERR, "dialresponse: ioctl I4B_DIALOUT_RESP failed: %s", strerror(errno)); + do_exit(1); + } + + DBGL(DL_DRVR, (log(LL_DBG, "dialresponse: sent [%s]", stattab[dstat]))); +} +/* EOF */ + diff --git a/usr.sbin/i4b/isdnd/timer.c b/usr.sbin/i4b/isdnd/timer.c new file mode 100644 index 0000000..5534efe --- /dev/null +++ b/usr.sbin/i4b/isdnd/timer.c @@ -0,0 +1,411 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - timer/timing support routines + * ------------------------------------------ + * + * $Id: timer.c,v 1.16 1998/12/05 18:03:43 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:13:10 1998] + * + *---------------------------------------------------------------------------*/ + +#include "isdnd.h" + +static int hr_callgate(void); +static void handle_reserved(cfg_entry_t *cep, time_t now); +static void handle_active(cfg_entry_t *cep, time_t now); +static void recover_illegal(cfg_entry_t *cep); + +/*---------------------------------------------------------------------------* + * recover from illegal state + *---------------------------------------------------------------------------*/ +static void +recover_illegal(cfg_entry_t *cep) +{ + log(LL_ERR, "recover_illegal: ERROR, entry %s attempting disconnect!", cep->name); + sendm_disconnect_req(cep, (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL); + log(LL_ERR, "recover_illegal: ERROR, entry %s - reset state/cdid!", cep->name); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; +} + +/*---------------------------------------------------------------------------* + * start the timer + *---------------------------------------------------------------------------*/ +void +start_timer(cfg_entry_t *cep, int seconds) +{ + cep->timerval = cep->timerremain = seconds; +} + +/*---------------------------------------------------------------------------* + * stop the timer + *---------------------------------------------------------------------------*/ +void +stop_timer(cfg_entry_t *cep) +{ + cep->timerval = cep->timerremain = 0; +} + +/*---------------------------------------------------------------------------* + * callgate for handle_recovery() + *---------------------------------------------------------------------------*/ +static int +hr_callgate(void) +{ + static int tv_first = 1; + static struct timeval tv_last; + struct timeval tv_now; + + /* there must be 1 sec minimum between calls to this section */ + + if(tv_first) + { + gettimeofday(&tv_last, NULL); + tv_first = 0; + } + + gettimeofday(&tv_now, NULL); + + if((tv_now.tv_sec - tv_last.tv_sec) < 1) + { + + DBGL(DL_TIME, (log(LL_DBG, "time < 1 - last %ld:%ld now %ld:%ld", + tv_last.tv_sec, tv_last.tv_usec, + tv_now.tv_sec, tv_now.tv_usec))); + return(1); + } + else if((tv_now.tv_sec - tv_last.tv_sec) == 1) + { + if(((1000000 - tv_last.tv_usec) + tv_now.tv_usec) < 900000) + { + DBGL(DL_TIME, (log(LL_DBG, "time < 900000us - last %ld:%ld now %ld:%ld", + tv_last.tv_sec, tv_last.tv_usec, + tv_now.tv_sec, tv_now.tv_usec))); + return(1); + } + } + + DBGL(DL_TIME, (log(LL_DBG, "time OK! - last %ld:%ld now %ld:%ld", + tv_last.tv_sec, tv_last.tv_usec, + tv_now.tv_sec, tv_now.tv_usec))); + + gettimeofday(&tv_last, NULL); + + return(0); +} + +/*---------------------------------------------------------------------------* + * timeout, recovery and retry handling + *---------------------------------------------------------------------------*/ +void +handle_recovery(void) +{ + cfg_entry_t *cep = NULL; + int i; + time_t now; + + if(hr_callgate()) /* last call to handle_recovery < 1 sec ? */ + return; /* yes, exit */ + + now = time(NULL); /* get current time */ + + /* walk thru all entries, look for work to do */ + + for(i=0; i < nentries; i++) + { + cep = &cfg_entry_tab[i]; /* ptr to config entry */ + + switch(cep->cdid) + { + case CDID_UNUSED: /* entry unused */ + continue; + break; + + case CDID_RESERVED: /* entry reserved */ + handle_reserved(cep, now); + break; + + default: /* entry in use */ + handle_active(cep, now); + break; + } + } +} + +/*---------------------------------------------------------------------------* + * timeout, recovery and retry handling for active entry + *---------------------------------------------------------------------------*/ +static void +handle_active(cfg_entry_t *cep, time_t now) +{ + switch(cep->state) + { + case ST_ACCEPTED: + if(cep->timerval && (--(cep->timerremain)) <= 0) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_active: entry %s, TIMEOUT !!!", cep->name))); + cep->timerval = cep->timerremain = 0; + next_state(cep, EV_TIMO); + } + break; + + case ST_ALERT: + if(cep->alert_time > 0) + { + cep->alert_time--; + } + else + { + log(LL_CHD, "%05d %s answering: incoming call from %s to %s", + cep->cdid, cep->name, + cep->real_phone_incoming, + cep->local_phone_incoming); + next_state(cep, EV_MCI); + } + break; + + case ST_ILL: + recover_illegal(cep); + break; + + default: + /* check hangup flag: if active, close connection */ + + if(cep->hangup) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_active: entry %s, hangup request!", cep->name))); + cep->hangup = 0; + next_state(cep, EV_DRQ); + } + + /* + * if shorthold mode is rates based, check if + * we entered a time with a new unit length + */ + + if(cep->unitlengthsrc == ULSRC_RATE) + { + int connecttime = (int)difftime(now, cep->connect_time); + + if((connecttime > 1) && + (connecttime % 60)) + { + int newrate = get_current_rate(cep, 0); + + if(newrate != cep->unitlength) + { + DBGL(DL_MSG, (log(LL_DBG, "handle_active: rates unit length updated %d -> %d", cep->unitlength, newrate))); + + cep->unitlength = newrate; + + unitlen_chkupd(cep); + } + } + } + break; + } +} + +/*---------------------------------------------------------------------------* + * timeout, recovery and retry handling for reserved entry + *---------------------------------------------------------------------------*/ +static void +handle_reserved(cfg_entry_t *cep, time_t now) +{ + time_t waittime; + + switch(cep->state) + { + case ST_DIALRTMRCHD: /* wait for dial retry time reached */ + + if(cep->dialrandincr) + waittime = cep->randomtime; + else + waittime = cep->recoverytime; + + + if(now > (cep->last_dial_time + waittime)) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: entry %s, dial retry request!", cep->name))); + cep->state = ST_DIALRETRY; + + if((cep->cdid = get_cdid()) == 0) + { + log(LL_ERR, "handle_reserved: dialretry get_cdid() returned 0!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + + if((setup_dialout(cep)) == GOOD) + { + sendm_connect_req(cep); + } + else + { + log(LL_ERR, "handle_reserved: dialretry setup_dialout returned ERROR!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + } + break; + + + case ST_ACB_WAITDIAL: /* active callback wait for time between disconnect and dial */ + + if(now > (cep->last_release_time + cep->callbackwait)) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: entry %s, callback dial!", cep->name))); + cep->state = ST_ACB_DIAL; + + if((cep->cdid = get_cdid()) == 0) + { + log(LL_ERR, "handle_reserved: callback get_cdid() returned 0!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + + select_first_dialno(cep); + + if((setup_dialout(cep)) == GOOD) + { + sendm_connect_req(cep); + } + else + { + log(LL_ERR, "handle_reserved: callback setup_dialout returned ERROR!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + } + break; + + case ST_ACB_DIALFAIL: /* callback to remote failed */ + + if(cep->dialrandincr) + waittime = cep->randomtime + cep->recoverytime; + else + waittime = cep->recoverytime; + + if(now > (cep->last_release_time + waittime)) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: entry %s, callback dial retry request!", cep->name))); + cep->state = ST_ACB_DIAL; + + if((cep->cdid = get_cdid()) == 0) + { + log(LL_ERR, "handle_reserved: callback dialretry get_cdid() returned 0!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + + if((setup_dialout(cep)) == GOOD) + { + sendm_connect_req(cep); + } + else + { + log(LL_ERR, "handle_reserved: callback dialretry setup_dialout returned ERROR!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + } + break; + + case ST_PCB_WAITCALL: /* wait for remote calling back */ + + if(now > (cep->last_release_time + cep->calledbackwait)) + { + cep->dial_count++; + + if(cep->dial_count < cep->dialretries) + { + /* inside normal retry cycle */ + + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: entry %s, retry calledback dial #%d!", + cep->name, cep->dial_count))); + cep->state = ST_PCB_DIAL; + + if((cep->cdid = get_cdid()) == 0) + { + log(LL_ERR, "handle_reserved: calledback get_cdid() returned 0!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + select_next_dialno(cep); + + if((setup_dialout(cep)) == GOOD) + { + sendm_connect_req(cep); + } + else + { + log(LL_ERR, "handle_reserved: calledback setup_dialout returned ERROR!"); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + return; + } + } + else + { + /* retries exhausted */ + + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: calledback dial retries exhausted"))); + dialresponse(cep, DSTAT_TFAIL); + cep->cdid = CDID_UNUSED; + cep->dial_count = 0; + cep->state = ST_IDLE; + } + } + break; + + case ST_DOWN: /* interface was taken down */ + + if(now > (cep->went_down_time + cep->downtime)) + { + DBGL(DL_RCVRY, (log(LL_DBG, "handle_reserved: taking %s%d up", bdrivername(cep->usrdevicename), cep->usrdeviceunit))); + if_up(cep); + cep->state = ST_IDLE; + cep->cdid = CDID_UNUSED; + } + break; + + case ST_ILL: /* illegal state reached, recover ! */ + + recover_illegal(cep); + break; + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdnd/vararray.h b/usr.sbin/i4b/isdnd/vararray.h new file mode 100644 index 0000000..c71f816 --- /dev/null +++ b/usr.sbin/i4b/isdnd/vararray.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1997, 1998 Martin Husemann <martin@rumolt.teuto.de> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. The name of the author may not be used to endorse or promote products + * derived from this software withough specific prior written permission + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * vararray.h: basic collection macros for variable sized (growing) arrays: + * macro version of popular C++ template classes, + * not as elegant in use as the template version, + * but has maximum runtime performance and can give + * pointers to array contents (i.e. for ioctl's). + * Works in C as well as in C++. + * CAVEAT: in C++ only useable for aggregateable objects, + * it does use memcpy instead of copy constructors! + */ + +#ifndef VARARRAY_H +#define VARARRAY_H +/* declare a variable sized array, element type is t */ +#define VARA_DECL(t) struct { int used, allocated; t *data; } + +/* aggregate initializer for a variable array */ +#define VARA_INITIALIZER { 0, 0, NULL } + +/* free all allocated storage */ +#define VARA_FREE(a) { if ((a).data != NULL) free((a).data); \ + (a).allocated = 0; (a).used = 0; } + +/* number of elments currently in array*/ +#define VARA_NUM(a) ((a).used) + +/* number of elements already allocated in array */ +#define VARA_ALLOCATED(a) ((a).allocated) + +/* pointer to array data */ +#define VARA_PTR(a) ((a).data) + +/* empty the array */ +#define VARA_EMPTY(a) { (a).used = 0; } + +#ifdef __cplusplus +#define VARA_NEW(t,c) new t[c] +#define VARA_DELETE(p) delete [] p +#else +#define VARA_NEW(t,c) (t*)malloc(sizeof(t)*(c)) +#define VARA_DELETE(p) free(p) +#endif + +/* add an element (not changing any data). + * a is the array, i the index, + * t the element type and n the initial allocation */ +#define VARA_ADD_AT(a,i,t,n) \ +{ \ + if ((i) >= (a).allocated) { \ + int new_alloc = (a).allocated ? (a).allocated*2 : (n); \ + t *new_data; \ + if (new_alloc <= (i)) new_alloc = (i)+1; \ + new_data = VARA_NEW(t, new_alloc); \ + if ((a).data) { \ + memcpy(new_data, (a).data, (a).used*sizeof(t)); \ + VARA_DELETE((a).data); \ + } \ + (a).data = new_data; \ + (a).allocated = new_alloc; \ + } \ + if ((i) >= (a).used) { \ + if (i > (a).used) \ + memset(&((a).data[(a).used]), 0, \ + sizeof(t)*((i)-(a).used+1)); \ + (a).used = (i)+1; \ + } \ +} + +/* return an l-value at index i */ +#define VARA_AT(a,i) ((a).data[(i)]) + +/* iterate through the array */ +#define VARA_FOREACH(a,i) for ((i) = 0; (i) < (a).used; (i)++) + +/* check for a valid index */ +#define VARA_VALID(a,i) ((i) >= 0 && (i) < (a).used) + +/* remove one entry */ +#define VARA_REMOVEAT(a,i) \ +{ \ + if ((i) < ((a).used -1)) \ + memmove(&((a).data[(i)]), &((a).data[(i)+1]), sizeof((a).data[0])); \ + (a).used--; \ +} + +/* free all storage allocated for the array */ +#define VARA_DESTROY(a) \ +{ \ + if ((a).data) VARA_DELETE((a).data); \ + (a).allocated = 0; \ + (a).used = 0; \ + (a).data = NULL; \ +} + +#endif + diff --git a/usr.sbin/i4b/isdndebug/Makefile b/usr.sbin/i4b/isdndebug/Makefile new file mode 100644 index 0000000..cf52818 --- /dev/null +++ b/usr.sbin/i4b/isdndebug/Makefile @@ -0,0 +1,5 @@ +PROG = isdndebug +SRCS = main.c +MAN8 = isdndebug.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/isdndebug/isdndebug.8 b/usr.sbin/i4b/isdndebug/isdndebug.8 new file mode 100644 index 0000000..f3903e3 --- /dev/null +++ b/usr.sbin/i4b/isdndebug/isdndebug.8 @@ -0,0 +1,102 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdndebug.8,v 1.4 1998/12/05 18:03:47 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:13:34 1998] +.\" +.\" -hm writing manual pages +.\" -hm getting uptodate +.\" +.\" +.Dd July 9, 1998 +.Dt isdndebug 8 +.Sh NAME +.Nm isdndebug +.Nd control debugging handling inside isdn4bsd kernel +.Sh SYNOPSIS +.Nm +.Op Fl e +.Op Fl g +.Op Fl h +.Op Fl l Ar layer +.Op Fl m +.Op Fl r +.Op Fl s Ar value +.Op Fl u Ar unit +.Op Fl z +.Op Fl H +.Sh DESCRIPTION +.Nm isdndebug +is part of the isdn4bsd package and is used to control debugging output +of the isdn4bsd kernel part. Every layer of the isdn4bsd kernel uses a +debugging mask which can be manipulated using this utility. +.Pp +A second usage of +.Nm +is to display and reset the HSCX error counters. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl e +Set debugging mask for the selected layer(s) to display errors only. +.It Fl g +Get the debugging mask for the selected layer(s). +.It Fl h +Display the the HSCX error counters. +.It Fl l +Specify the layer for which a command applies. Default is all layers. +.It Fl m +Set debugging mask for the selected layer(s) to display all possible +debugging messages (maximum output). +.It Fl r +Set debugging mask for the selected layer(s) to the compiled in default +(reset). +.It Fl s +Set debugging mask for the selected layer(s) to value. Value can be +specified in any number base supported by +.Xr sscanf 3 . +.It Fl u +Set the unit numbers for the -h and -H flags. +.It Fl z +Set debugging mask for the selected layer(s) to no output at all (zero). +.It Fl H +Reset the HSCX error counters to zero. +.Pp +.Sh FILES +/dev/i4bctl + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +isdndebug -g +.Ed +.Pp +displays the current debugging level for all ISDN layers + +.Sh AUTHOR +The +.Nm +utility and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/isdndebug/main.c b/usr.sbin/i4b/isdndebug/main.c new file mode 100644 index 0000000..7fdbf7f --- /dev/null +++ b/usr.sbin/i4b/isdndebug/main.c @@ -0,0 +1,553 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * main.c - i4b set debug options + * ------------------------------ + * + * $Id: main.c,v 1.13 1998/12/05 18:03:49 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:13:55 1998] + * + *---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> + +#include <machine/i4b_debug.h> +#include <machine/i4b_ioctl.h> + +char *bin_str(unsigned long val, int length); + +static void usage ( void ); +void printl1(unsigned long val); +void printl2(unsigned long val); +void printl3(unsigned long val); +void printl4(unsigned long val); + +static int isdnfd; + +#define I4BCTLDEVICE "/dev/i4bctl" + +int opt_get = 0; +int opt_layer = -1; +int opt_set = 0; +int opt_setval; +int opt_reset = 0; +int opt_max = 0; +int opt_err = 0; +int opt_zero = 0; +int opt_unit = 0; +int opt_hscx = 0; +int opt_rhscx = 0; + +/*---------------------------------------------------------------------------* + * program entry + *---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int c; + ctl_debug_t cdbg; + int ret; + + while ((c = getopt(argc, argv, "eghl:mrs:u:zH?")) != EOF) + { + switch(c) + { + case 'e': + opt_err = 1; + break; + + case 'g': + opt_get = 1; + break; + + case 'h': + opt_hscx = 1; + break; + + case 'r': + opt_reset = 1; + break; + + case 'm': + opt_max = 1; + break; + + case 'l': + opt_layer = atoi(optarg); + if(opt_layer < 1 || opt_layer > 4) + usage(); + break; + + case 's': + if((sscanf(optarg, "%i", &opt_setval)) != 1) + usage(); + opt_set = 1; + break; + + case 'u': + opt_unit = atoi(optarg); + if(opt_unit < 0 || opt_unit > 9) + usage(); + break; + + case 'z': + opt_zero = 1; + break; + + case 'H': + opt_rhscx = 1; + break; + + case '?': + default: + usage(); + break; + } + } + + if(opt_get == 0 && opt_set == 0 && opt_reset == 0 && opt_max == 0 && + opt_err == 0 && opt_zero == 0 && opt_hscx == 0 && opt_rhscx == 0) + { + usage(); + } + + if((opt_get + opt_set + opt_reset + opt_max + opt_err + opt_zero + + opt_hscx + opt_rhscx) > 1) + { + usage(); + } + + if((isdnfd = open(I4BCTLDEVICE, O_RDWR)) < 0) + { + fprintf(stderr, "i4bctl: cannot open %s: %s\n", I4BCTLDEVICE, strerror(errno)); + exit(1); + } + + if(opt_hscx) + { + hscxstat_t hst; + + hst.unit = opt_unit; + hst.chan = 0; + + if((ret = ioctl(isdnfd, I4B_CTL_GET_HSCXSTAT, &hst)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_GET_HSCXSTAT failed: %s", strerror(errno)); + exit(1); + } + + printf("\nHSCX events: VFR RDO CRC RAB XDU RFO\n"); + + printf("unit %d chan %d: %6d %6d %6d %6d %6d %6d\n", + hst.unit, hst.chan, + hst.vfr, hst.rdo, hst.crc, hst.rab, hst.xdu, hst.rfo); + + hst.unit = opt_unit; + hst.chan = 1; + + if((ret = ioctl(isdnfd, I4B_CTL_GET_HSCXSTAT, &hst)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_GET_HSCXSTAT failed: %s", strerror(errno)); + exit(1); + } + + printf("unit %d chan %d: %6d %6d %6d %6d %6d %6d\n", + hst.unit, hst.chan, + hst.vfr, hst.rdo, hst.crc, hst.rab, hst.xdu, hst.rfo); + + exit(0); + } + + if(opt_rhscx) + { + hscxstat_t hst; + + hst.unit = opt_unit; + hst.chan = 0; + + if((ret = ioctl(isdnfd, I4B_CTL_CLR_HSCXSTAT, &hst)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_CLR_HSCXSTAT failed: %s", strerror(errno)); + exit(1); + } + + printf("HSCX event counters unit %d chan %d reset to zero!\n", + hst.unit, hst.chan); + + hst.unit = opt_unit; + hst.chan = 1; + + if((ret = ioctl(isdnfd, I4B_CTL_CLR_HSCXSTAT, &hst)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_CLR_HSCXSTAT failed: %s", strerror(errno)); + exit(1); + } + + printf("HSCX event counters unit %d chan %d reset to zero!\n", + hst.unit, hst.chan); + + exit(0); + } + + if((ret = ioctl(isdnfd, I4B_CTL_GET_DEBUG, &cdbg)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_GET_DEBUG failed: %s", strerror(errno)); + exit(1); + } + + if(opt_get) + { + switch(opt_layer) + { + case -1: + printl1(cdbg.l1); + printl2(cdbg.l2); + printl3(cdbg.l3); + printl4(cdbg.l4); + break; + + case 1: + printl1(cdbg.l1); + break; + + case 2: + printl2(cdbg.l2); + break; + + case 3: + printl3(cdbg.l3); + break; + + case 4: + printl4(cdbg.l4); + break; + } + printf("\n"); + return(0); + } + else if(opt_set) + { + switch(opt_layer) + { + case -1: + usage(); + break; + + case 1: + cdbg.l1 = opt_setval; + break; + + case 2: + cdbg.l2 = opt_setval; + break; + + case 3: + cdbg.l3 = opt_setval; + break; + + case 4: + cdbg.l4 = opt_setval; + break; + } + } + else if(opt_reset) + { + switch(opt_layer) + { + case -1: + cdbg.l1 = L1_DEBUG_DEFAULT; + cdbg.l2 = L2_DEBUG_DEFAULT; + cdbg.l3 = L3_DEBUG_DEFAULT; + cdbg.l4 = L4_DEBUG_DEFAULT; + break; + + case 1: + cdbg.l1 = L1_DEBUG_DEFAULT; + break; + + case 2: + cdbg.l2 = L2_DEBUG_DEFAULT; + break; + + case 3: + cdbg.l3 = L3_DEBUG_DEFAULT; + break; + + case 4: + cdbg.l4 = L4_DEBUG_DEFAULT; + break; + } + } + else if(opt_max) + { + switch(opt_layer) + { + case -1: + cdbg.l1 = L1_DEBUG_MAX; + cdbg.l2 = L2_DEBUG_MAX; + cdbg.l3 = L3_DEBUG_MAX; + cdbg.l4 = L4_DEBUG_MAX; + break; + + case 1: + cdbg.l1 = L1_DEBUG_MAX; + break; + + case 2: + cdbg.l2 = L2_DEBUG_MAX; + break; + + case 3: + cdbg.l3 = L3_DEBUG_MAX; + break; + + case 4: + cdbg.l4 = L4_DEBUG_MAX; + break; + } + } + else if(opt_err) + { + switch(opt_layer) + { + case -1: + cdbg.l1 = L1_DEBUG_ERR; + cdbg.l2 = L2_DEBUG_ERR; + cdbg.l3 = L3_DEBUG_ERR; + cdbg.l4 = L4_DEBUG_ERR; + break; + + case 1: + cdbg.l1 = L1_DEBUG_ERR; + break; + + case 2: + cdbg.l2 = L2_DEBUG_ERR; + break; + + case 3: + cdbg.l3 = L3_DEBUG_ERR; + break; + + case 4: + cdbg.l4 = L4_DEBUG_ERR; + break; + } + } + else if(opt_zero) + { + switch(opt_layer) + { + case -1: + cdbg.l1 = 0; + cdbg.l2 = 0; + cdbg.l3 = 0; + cdbg.l4 = 0; + break; + + case 1: + cdbg.l1 = 0; + break; + + case 2: + cdbg.l2 = 0; + break; + + case 3: + cdbg.l3 = 0; + break; + + case 4: + cdbg.l4 = 0; + break; + } + } + else + { + exit(1); + } + + if((ret = ioctl(isdnfd, I4B_CTL_SET_DEBUG, &cdbg)) < 0) + { + fprintf(stderr, "ioctl I4B_CTL_SET_DEBUG failed: %s", strerror(errno)); + exit(1); + } + return(0); +} + +/*---------------------------------------------------------------------------* + * return ptr to string of 1's and 0's for value + *---------------------------------------------------------------------------*/ +char * +bin_str(unsigned long val, int length) +{ + static char buffer[80]; + int i = 0; + + if (length > 32) + length = 32; + + val = val << (32 - length); + + while (length--) + { + if (val & 0x80000000) + buffer[i++] = '1'; + else + buffer[i++] = '0'; + if ((length % 4) == 0 && length) + buffer[i++] = '.'; + val = val << 1; + } + return (buffer); +} + +/*---------------------------------------------------------------------------* + * print l1 info + *---------------------------------------------------------------------------*/ +void +printl1(unsigned long val) +{ + printf("\nLayer 1: %s = 0x%lX\n", bin_str(val, 32), val); + printf(" || |||| |||| ||||\n"), + printf(" || |||| |||| |||+- general error messages\n"); + printf(" || |||| |||| ||+-- PH primitives exchanged\n"); + printf(" || |||| |||| |+--- B channel actions\n"); + printf(" || |||| |||| +---- HSCX error messages\n"); + printf(" || |||| |||+------ HSCX IRQ messages\n"); + printf(" || |||| ||+------- ISAC error messages\n"); + printf(" || |||| |+-------- ISAC messages\n"); + printf(" || |||| +--------- ISAC setup messages\n"); + printf(" || |||+----------- FSM general messages\n"); + printf(" || ||+------------ FSM error messages\n"); + printf(" || |+------------- timer general messages\n"); + printf(" || +-------------- timer error messages\n"); + printf(" |+---------------- HSCX data xfer errors msgs\n"); + printf(" +----------------- ISAC CICO messages\n"); + printf(" ++++-++++-++++-++++-++------------------ unassigned\n"); +} + +/*---------------------------------------------------------------------------* + * print l2 info + *---------------------------------------------------------------------------*/ +void +printl2(unsigned long val) +{ + printf("\nLayer 2: %s = 0x%lX\n", bin_str(val, 32), val); + printf(" || |||| |||| ||||\n"), + printf(" || |||| |||| |||+- general error messages\n"); + printf(" || |||| |||| ||+-- DL primitives exchanged\n"); + printf(" || |||| |||| |+--- U frame messages\n"); + printf(" || |||| |||| +---- U frame error messages\n"); + printf(" || |||| |||+------ S frame messages\n"); + printf(" || |||| ||+------- S frame error messages\n"); + printf(" || |||| |+-------- I frame messages\n"); + printf(" || |||| +--------- I frame error messages\n"); + printf(" || |||+----------- FSM general messages\n"); + printf(" || ||+------------ FSM error messages\n"); + printf(" || |+------------- timer general messages\n"); + printf(" || +-------------- timer error messages\n"); + printf(" |+---------------- TEI general messages\n"); + printf(" +----------------- TEI error messages\n"); + printf(" ++++-++++-++++-++++-++------------------ unassigned\n"); +} + +/*---------------------------------------------------------------------------* + * print l3 info + *---------------------------------------------------------------------------*/ +void +printl3(unsigned long val) +{ + printf("\nLayer 3: %s = 0x%lX\n", bin_str(val, 32), val); + printf(" ||| |||| ||||\n"), + printf(" ||| |||| |||+- general error messages\n"); + printf(" ||| |||| ||+-- general messages\n"); + printf(" ||| |||| |+--- FSM messages\n"); + printf(" ||| |||| +---- FSM error messages\n"); + printf(" ||| |||+------ timer messages\n"); + printf(" ||| ||+------- timer error messages\n"); + printf(" ||| |+-------- protocol messages\n"); + printf(" ||| +--------- protocol error messages\n"); + printf(" ||+----------- facility messages\n"); + printf(" |+------------ facility error messages\n"); + printf(" +------------- Q.931 messages exchanged\n"); + printf(" ++++-++++-++++-++++-++++-++------------- unassigned\n"); +} + +/*---------------------------------------------------------------------------* + * print l4 info + *---------------------------------------------------------------------------*/ +void +printl4(unsigned long val) +{ + printf("\nLayer 4: %s = 0x%lX\n", bin_str(val, 32), val); + printf(" || ||||\n"), + printf(" || |||+- general error messages\n"); + printf(" || ||+-- general messages\n"); + printf(" || |+--- B-ch timeout messages\n"); + printf(" || +---- network driver dial state\n"); + printf(" |+------ ipr driver debug messages\n"); + printf(" +------- rbch driver debug messages\n"); + printf(" ++++-++++-++++-++++-++++-++++-++-------- unassigned\n"); +} + +/*---------------------------------------------------------------------------* + * usage display and exit + *---------------------------------------------------------------------------*/ +static void +usage(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, "isdndebug - i4b set debug level, version %02d.%02d, compiled %s %s\n", VERSION, REL, __DATE__, __TIME__); + fprintf(stderr, "usage: isdndebug -e -h -g -l <layer> -m -r -s <value> -u <unit> -z -H\n"); + fprintf(stderr, " -e set error only debugging output\n"); + fprintf(stderr, " -g get current debugging values\n"); + fprintf(stderr, " -h get HSCX event counters\n"); + fprintf(stderr, " -l layer specify layer (1...4)\n"); + fprintf(stderr, " -m set maximum debugging output\n"); + fprintf(stderr, " -r reset values(s) to compiled in default\n"); + fprintf(stderr, " -s value set new debugging value for layer\n"); + fprintf(stderr, " -u unit unit number for -h and -H commands\n"); + fprintf(stderr, " -z set zero (=no) debugging output\n"); + fprintf(stderr, " -H reset HSCX event counters to zero\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/Makefile b/usr.sbin/i4b/isdndecode/Makefile new file mode 100644 index 0000000..cad91437 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/Makefile @@ -0,0 +1,7 @@ +PROG = isdndecode +SRCS = main.c layer1.c layer2.c layer3.c \ + layer3_subr.c facility.c pcause.c +MAN8 = isdndecode.8 + +.include <bsd.prog.mk> + diff --git a/usr.sbin/i4b/isdndecode/decode.h b/usr.sbin/i4b/isdndecode/decode.h new file mode 100644 index 0000000..0eec0ab --- /dev/null +++ b/usr.sbin/i4b/isdndecode/decode.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * decode.h - isdndecode header file + * --------------------------------- + * + * $Id: decode.h,v 1.4 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:10:13 1998] + * + *---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <signal.h> +#include <fcntl.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/file.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include "pcause.h" + +#define I4BTRC_DEVICE "/dev/i4btrc" /* trace device file */ +#define DECODE_FILE_NAME "isdndecode" /* default output filename */ +#define DECODE_FILE_NAME_BAK ".last" /* backup filename trailer */ +#define BIN_FILE_NAME "isdntracebin" /* default binary filename */ + +#define BSIZE 4096 /* read buffer size */ +#define NCOLS 80 /* screen width */ + +#define RxUDEF 0 /* analyze mode, default unit for receiver side */ +#define TxUDEF 1 /* analyze mode, default unit for transmitter side */ + +void layer1(char *pbuf, unsigned char *buf); +int layer2(char *pbuf, unsigned char *buf, int is_te, int printit); +void layer3(char *pbuf, int n, int off, unsigned char *buf); +int q932_facility(char *pbuf, unsigned char *buf); +void sprintline(int, char *, int, int, int, const char *, ...); +void extension(int, char *, int, unsigned char, unsigned char); + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/facility.c b/usr.sbin/i4b/isdndecode/facility.c new file mode 100644 index 0000000..5735abb --- /dev/null +++ b/usr.sbin/i4b/isdndecode/facility.c @@ -0,0 +1,906 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * facility.c - decode Q.932 facilities + * ------------------------------------ + * + * $Id: facility.c,v 1.2 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:10:32 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" +#include "facility.h" + +static int do_component(int length, char *pbuf); +static char *uni_str(int code); +static char *opval_str(int val); +static char *bid_str(int val); +static void next_state(char *pbuf, int class, int form, int code, int val); + +static int byte_len; +static unsigned char *byte_buf; +static int state; + +/*---------------------------------------------------------------------------* + * decode Q.931/Q.932 facility info element + *---------------------------------------------------------------------------*/ +int +q932_facility(char *pbuf, unsigned char *buf) +{ + int len; + + sprintf((pbuf+strlen(pbuf)), "[facility (Q.932): "); + + buf++; /* length */ + + len = *buf; + + buf++; /* protocol profile */ + + sprintf((pbuf+strlen(pbuf)), "Protocol="); + + switch(*buf & 0x1f) + { + case FAC_PROTO_ROP: + sprintf((pbuf+strlen(pbuf)), "Remote Operations Protocol\n"); + break; + + case FAC_PROTO_CMIP: + sprintf((pbuf+strlen(pbuf)), "CMIP Protocol (Q.941), UNSUPPORTED!\n"); + return(len+2); + break; + + case FAC_PROTO_ACSE: + sprintf((pbuf+strlen(pbuf)), "ACSE Protocol (X.217/X.227), UNSUPPORTED!\n"); + return(len+2); + break; + + default: + sprintf((pbuf+strlen(pbuf)), "Unknown Protocol (val = 0x%x), UNSUPPORTED!\n", *buf & 0x1f); + return(len+2); + break; + } + + /* next byte */ + + buf++; + len--; + + /* initialize variables for do_component */ + + byte_len = 0; + byte_buf = buf; + state = ST_EXP_COMP_TYP; + + /* decode facility */ + + do_component(len, pbuf); + + sprintf((pbuf+(strlen(pbuf)-1)), "]"); /* XXX replace last newline */ + + return(len+3); +} + +/*---------------------------------------------------------------------------* + * handle a component recursively + *---------------------------------------------------------------------------*/ +static int +do_component(int length, char *pbuf) +{ + int comp_tag_class; /* component tag class */ + int comp_tag_form; /* component form: constructor or primitive */ + int comp_tag_code; /* component code depending on class */ + int comp_length = 0; /* component length */ + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "ENTER - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + +again: + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "AGAIN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + + /*----------------------------------------*/ + /* first component element: component tag */ + /*----------------------------------------*/ + + /* tag class bits */ + + sprintf((pbuf+strlen(pbuf)), "\t0x%02x Tag: ", *byte_buf); + + comp_tag_class = (*byte_buf & 0xc0) >> 6; + + switch(comp_tag_class) + { + case FAC_TAGCLASS_UNI: + sprintf((pbuf+strlen(pbuf)), "Universal"); + break; + case FAC_TAGCLASS_APW: + sprintf((pbuf+strlen(pbuf)), "Applic-wide"); + break; + case FAC_TAGCLASS_COS: + sprintf((pbuf+strlen(pbuf)), "Context-spec"); + break; + case FAC_TAGCLASS_PRU: + sprintf((pbuf+strlen(pbuf)), "Private"); + break; + } + + /* tag form bit */ + + comp_tag_form = (*byte_buf & 0x20) > 5; + + sprintf((pbuf+strlen(pbuf)), ", "); + + if(comp_tag_form == FAC_TAGFORM_CON) + { + sprintf((pbuf+strlen(pbuf)), "Constructor"); + } + else + { + sprintf((pbuf+strlen(pbuf)), "Primitive"); + } + + /* tag code bits */ + + comp_tag_code = *byte_buf & 0x1f; + + sprintf((pbuf+strlen(pbuf)), ", "); + + if(comp_tag_code == 0x1f) + { + comp_tag_code = 0; + + byte_buf++; + byte_len++; + + while(*byte_buf & 0x80) + { + comp_tag_code += (*byte_buf & 0x7f); + byte_buf++; + byte_len++; + } + comp_tag_code += (*byte_buf & 0x7f); + sprintf((pbuf+strlen(pbuf)), "%d (ext)\n", comp_tag_code); + } + else + { + comp_tag_code = (*byte_buf & 0x1f); + + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + sprintf((pbuf+strlen(pbuf)), "%s (%d)\n", uni_str(comp_tag_code), comp_tag_code); + } + else + { + sprintf((pbuf+strlen(pbuf)), "code = %d\n", comp_tag_code); + } + } + + byte_buf++; + byte_len++; + + /*--------------------------------------------*/ + /* second component element: component length */ + /*--------------------------------------------*/ + + sprintf((pbuf+strlen(pbuf)), "\t0x%02x Len: ", *byte_buf); + + comp_length = 0; + + if(*byte_buf & 0x80) + { + int i = *byte_buf & 0x7f; + + byte_len += i; + + for(;i > 0;i++) + { + byte_buf++; + comp_length += (*byte_buf * (i*256)); + } + sprintf((pbuf+strlen(pbuf)), "%d (long form)\n", comp_length); + } + else + { + comp_length = *byte_buf & 0x7f; + sprintf((pbuf+strlen(pbuf)), "%d (short form)\n", comp_length); + } + + next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, -1); + + byte_len++; + byte_buf++; + + if(comp_length) + { + + /*---------------------------------------------*/ + /* third component element: component contents */ + /*---------------------------------------------*/ + + if(comp_tag_form) /* == constructor */ + { + do_component(comp_length, pbuf); + } + else + { + int val = 0; + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + switch(comp_tag_code) + { + case FAC_CODEUNI_INT: + case FAC_CODEUNI_ENUM: + case FAC_CODEUNI_BOOL: + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x ", *byte_buf); + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + sprintf((pbuf+strlen(pbuf)), "Val: %d\n", val); + } + break; + default: + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x = %d", *byte_buf, *byte_buf); + if(isprint(*byte_buf)) + sprintf((pbuf+strlen(pbuf)), " = '%c'", *byte_buf); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + } + break; + } + } + + else /* comp_tag_class != FAC_TAGCLASS_UNI */ + { + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x", *byte_buf); + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + sprintf((pbuf+strlen(pbuf)), "\n"); + } + } + next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, val); + } + } + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "PREGOTO - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + if(byte_len < length) + goto again; +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "RETURN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + return(byte_len); +} + +/*---------------------------------------------------------------------------* + * print universal id type + *---------------------------------------------------------------------------*/ +static char *uni_str(int code) +{ + static char *tbl[] = { + "BOOLEAN", + "INTEGER", + "BIT STRING", + "OCTET STRING", + "NULL", + "OBJECT IDENTIFIER", + "OBJECT DESCRIPTOR", + "EXTERNAL", + "REAL", + "ENUMERATED", + "RESERVED11", + "RESERVED12", + "RESERVED13", + "RESERVED14", + "RESERVED15", + "SEQUENCE", + "SET", + "NUMERIC STRING", + "PRINTABLE STRING", + "TELETEX STRING", + "ISO646 STRING", + "IA5 STRING", + "GRAPHIC STRING", + "GENERAL STRING" + }; + + if(code >= 1 && code <= FAC_CODEUNI_GNSTR) + return(tbl[code-1]); + else + return("ERROR, Value out of Range!"); +} + +/*---------------------------------------------------------------------------* + * print operation value + *---------------------------------------------------------------------------*/ +static char *opval_str(int val) +{ + static char buffer[80]; + char *r; + + switch(val) + { + case FAC_OPVAL_UUS: + r = "uUs"; + break; + case FAC_OPVAL_CUG: + r = "cUGCall"; + break; + case FAC_OPVAL_MCID: + r = "mCIDRequest"; + break; + case FAC_OPVAL_BTPY: + r = "beginTPY"; + break; + case FAC_OPVAL_ETPY: + r = "endTPY"; + break; + case FAC_OPVAL_ECT: + r = "eCTRequest"; + break; + case FAC_OPVAL_DIV_ACT: + r = "activationDiversion"; + break; + case FAC_OPVAL_DIV_DEACT: + r = "deactivationDiversion"; + break; + case FAC_OPVAL_DIV_ACTSN: + r = "activationStatusNotificationDiv"; + break; + case FAC_OPVAL_DIV_DEACTSN: + r = "deactivationStatusNotificationDiv"; + break; + case FAC_OPVAL_DIV_INTER: + r = "interrogationDiversion"; + break; + case FAC_OPVAL_DIV_INFO: + r = "diversionInformation"; + break; + case FAC_OPVAL_DIV_CALLDEF: + r = "callDeflection"; + break; + case FAC_OPVAL_DIV_CALLRER: + r = "callRerouting"; + break; + case FAC_OPVAL_DIV_LINF2: + r = "divertingLegInformation2"; + break; + case FAC_OPVAL_DIV_INVS: + r = "invokeStatus"; + break; + case FAC_OPVAL_DIV_INTER1: + r = "interrogationDiversion1"; + break; + case FAC_OPVAL_DIV_LINF1: + r = "divertingLegInformation1"; + break; + case FAC_OPVAL_DIV_LINF3: + r = "divertingLegInformation3"; + break; + case FAC_OPVAL_ER_CRCO: + r = "explicitReservationCreationControl"; + break; + case FAC_OPVAL_ER_MGMT: + r = "explicitReservationManagement"; + break; + case FAC_OPVAL_ER_CANC: + r = "explicitReservationCancel"; + break; + case FAC_OPVAL_MLPP_QUERY: + r = "mLPP lfb Query"; + break; + case FAC_OPVAL_MLPP_CALLR: + r = "mLPP Call Request"; + break; + case FAC_OPVAL_MLPP_CALLP: + r = "mLPP Call Preemption"; + break; + case FAC_OPVAL_AOC_REQ: + r = "chargingRequest"; + break; + case FAC_OPVAL_AOC_S_CUR: + r = "aOCSCurrency"; + break; + case FAC_OPVAL_AOC_S_SPC: + r = "aOCSSpecialArrangement"; + break; + case FAC_OPVAL_AOC_D_CUR: + r = "aOCDCurrency"; + break; + case FAC_OPVAL_AOC_D_UNIT: + r = "aOCDChargingUnit"; + break; + case FAC_OPVAL_AOC_E_CUR: + r = "aOCECurrency"; + break; + case FAC_OPVAL_AOC_E_UNIT: + r = "aOCEChargingUnit"; + break; + case FAC_OPVAL_AOC_IDOFCRG: + r = "identificationOfCharge"; + break; + case FAC_OPVAL_CONF_BEG: + r = "beginConf"; + break; + case FAC_OPVAL_CONF_ADD: + r = "addConf"; + break; + case FAC_OPVAL_CONF_SPLIT: + r = "splitConf"; + break; + case FAC_OPVAL_CONF_DROP: + r = "dropConf"; + break; + case FAC_OPVAL_CONF_ISOLATE: + r = "isolateConf"; + break; + case FAC_OPVAL_CONF_REATT: + r = "reattachConf"; + break; + case FAC_OPVAL_CONF_PDISC: + r = "partyDISC"; + break; + case FAC_OPVAL_CONF_FCONF: + r = "floatConf"; + break; + case FAC_OPVAL_CONF_END: + r = "endConf"; + break; + case FAC_OPVAL_CONF_IDCFE: + r = "indentifyConferee"; + break; + case FAC_OPVAL_REVC_REQ: + r = "requestREV"; + break; + default: + sprintf(buffer, "unknown operation value %d!", val); + r = buffer; + } + return(r); +} + +/*---------------------------------------------------------------------------* + * billing id string + *---------------------------------------------------------------------------*/ +static char *bid_str(int val) +{ + static char buffer[80]; + char *r; + + switch(val) + { + case 0: + r = "normalCharging"; + break; + case 1: + r = "reverseCharging"; + break; + case 2: + r = "creditCardCharging"; + break; + case 3: + r = "callForwardingUnconditional"; + break; + case 4: + r = "callForwardingBusy"; + break; + case 5: + r = "callForwardingNoReply"; + break; + case 6: + r = "callDeflection"; + break; + case 7: + r = "callTransfer"; + break; + default: + sprintf(buffer, "unknown billing-id value %d!", val); + r = buffer; + } + return(r); +} + +/*---------------------------------------------------------------------------* + * invoke component + *---------------------------------------------------------------------------*/ +static void +F_1_1(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_1, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t invokeComponent\n"); + state = ST_EXP_INV_ID; + } +} + +/*---------------------------------------------------------------------------* + * return result + *---------------------------------------------------------------------------*/ +static void +F_1_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_2, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t returnResult\n"); + state = ST_EXP_RR_INV_ID; + } +} +/*---------------------------------------------------------------------------* + * return error + *---------------------------------------------------------------------------*/ +static void +F_1_3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_3, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t returnError\n"); + state = ST_EXP_NIX; + } +} +/*---------------------------------------------------------------------------* + * reject + *---------------------------------------------------------------------------*/ +static void +F_1_4(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_4, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t reject\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * invoke component: invoke id + *---------------------------------------------------------------------------*/ +static void +F_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_2, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t InvokeIdentifier = %d\n", val); + state = ST_EXP_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * return result: invoke id + *---------------------------------------------------------------------------*/ +static void +F_RR2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR2, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t InvokeIdentifier = %d\n", val); + state = ST_EXP_RR_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * invoke component: operation value + *---------------------------------------------------------------------------*/ +static void +F_3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_3, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t Operation Value = %s (%d)\n", opval_str(val), val); + state = ST_EXP_INFO; + } +} + +/*---------------------------------------------------------------------------* + * return result: operation value + *---------------------------------------------------------------------------*/ +static void +F_RR3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR3, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t Operation Value = %s (%d)\n", opval_str(val), val); + state = ST_EXP_RR_RESULT; + } +} + +/*---------------------------------------------------------------------------* + * return result: RESULT + *---------------------------------------------------------------------------*/ +static void +F_RRR(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RRR, val = %d\n", val); +#endif + state = ST_EXP_NIX; +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t specificChargingUnits\n"); + state = ST_EXP_RUL; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4_1(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_1, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t freeOfCharge\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_2, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t chargeNotAvailable\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_5(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_5, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t recordedUnitsList [1]\n"); + state = ST_EXP_RU; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_6(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_6, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t RecordedUnits\n"); + state = ST_EXP_RNOU; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_7(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_7, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t NumberOfUnits = %d\n", val); + state = ST_EXP_TOCI; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_8(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_8, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t typeOfChargingInfo = %s\n", val == 0 ? "subTotal" : "total"); + state = ST_EXP_DBID; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_9(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_9, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t AOCDBillingId = %s (%d)\n", bid_str(val), val); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * state table + *---------------------------------------------------------------------------*/ +static struct statetab { + int currstate; /* input: current state we are in */ + int form; /* input: current tag form */ + int class; /* input: current tag class */ + int code; /* input: current tag code */ + void (*func)(char *,int); /* output: func to exec */ +} statetab[] = { + +/* current state tag form tag class tag code function */ +/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/ + +/* invoke */ + + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 }, + {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 }, + {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 }, + {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 }, + {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 }, + {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 }, + {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 }, + {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 }, + {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 }, + +/* return result */ + + {ST_EXP_RR_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_RR2 }, + {ST_EXP_RR_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_RR3 }, + {ST_EXP_RR_RESULT, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SET, F_RRR }, + +/* end */ + + {-1, -1, -1, -1, NULL } +}; + +/*---------------------------------------------------------------------------* + * state decode for do_component + *---------------------------------------------------------------------------*/ +static void +next_state(char *pbuf, int class, int form, int code, int val) +{ + int i; + +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: class=%d, form=%d, code=%d, val=%d\n", class, form, code, val); +#endif + + for(i=0; ; i++) + { + if((statetab[i].currstate > state) || + (statetab[i].currstate == -1)) + { + break; + } + + if((statetab[i].currstate == state) && + (statetab[i].form == form) && + (statetab[i].class == class) && + (statetab[i].code == code)) + { + (*statetab[i].func)(pbuf, val); + break; + } + } +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdndecode/facility.h b/usr.sbin/i4b/isdndecode/facility.h new file mode 100644 index 0000000..7080c22 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/facility.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * facility.h - Q.932 facility header file + * --------------------------------------- + * + * $Id: facility.h,v 1.2 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:10:48 1998] + * + *---------------------------------------------------------------------------*/ + +/* #define FAC_DEBUG */ +/* #define ST_DEBUG */ + +/* protocols */ +#define FAC_PROTO_ROP 0x11 +#define FAC_PROTO_CMIP 0x12 +#define FAC_PROTO_ACSE 0x13 + +/* tag classes */ +#define FAC_TAGCLASS_UNI 0x00 +#define FAC_TAGCLASS_APW 0x01 +#define FAC_TAGCLASS_COS 0x02 +#define FAC_TAGCLASS_PRU 0x03 + +/* tag forms */ +#define FAC_TAGFORM_PRI 0x00 +#define FAC_TAGFORM_CON 0x01 + +/* class UNIVERSAL values */ +#define FAC_CODEUNI_BOOL 1 +#define FAC_CODEUNI_INT 2 +#define FAC_CODEUNI_BITS 3 +#define FAC_CODEUNI_OCTS 4 +#define FAC_CODEUNI_NULL 5 +#define FAC_CODEUNI_OBJI 6 +#define FAC_CODEUNI_OBJD 7 +#define FAC_CODEUNI_EXT 8 +#define FAC_CODEUNI_REAL 9 +#define FAC_CODEUNI_ENUM 10 +#define FAC_CODEUNI_R11 11 +#define FAC_CODEUNI_R12 12 +#define FAC_CODEUNI_R13 13 +#define FAC_CODEUNI_R14 14 +#define FAC_CODEUNI_R15 15 +#define FAC_CODEUNI_SEQ 16 +#define FAC_CODEUNI_SET 17 +#define FAC_CODEUNI_NSTR 18 +#define FAC_CODEUNI_PSTR 19 +#define FAC_CODEUNI_TSTR 20 +#define FAC_CODEUNI_VSTR 21 +#define FAC_CODEUNI_ISTR 22 +#define FAC_CODEUNI_UTIME 23 +#define FAC_CODEUNI_GTIME 24 +#define FAC_CODEUNI_GSTR 25 +#define FAC_CODEUNI_VISTR 26 +#define FAC_CODEUNI_GNSTR 27 + +/* operation values */ +#define FAC_OPVAL_UUS 1 +#define FAC_OPVAL_CUG 2 +#define FAC_OPVAL_MCID 3 +#define FAC_OPVAL_BTPY 4 +#define FAC_OPVAL_ETPY 5 +#define FAC_OPVAL_ECT 6 + +#define FAC_OPVAL_DIV_ACT 7 +#define FAC_OPVAL_DIV_DEACT 8 +#define FAC_OPVAL_DIV_ACTSN 9 +#define FAC_OPVAL_DIV_DEACTSN 10 +#define FAC_OPVAL_DIV_INTER 11 +#define FAC_OPVAL_DIV_INFO 12 +#define FAC_OPVAL_DIV_CALLDEF 13 +#define FAC_OPVAL_DIV_CALLRER 14 +#define FAC_OPVAL_DIV_LINF2 15 +#define FAC_OPVAL_DIV_INVS 16 +#define FAC_OPVAL_DIV_INTER1 17 +#define FAC_OPVAL_DIV_LINF1 18 +#define FAC_OPVAL_DIV_LINF3 19 + +#define FAC_OPVAL_ER_CRCO 20 +#define FAC_OPVAL_ER_MGMT 21 +#define FAC_OPVAL_ER_CANC 22 + +#define FAC_OPVAL_MLPP_QUERY 24 +#define FAC_OPVAL_MLPP_CALLR 25 +#define FAC_OPVAL_MLPP_CALLP 26 + +#define FAC_OPVAL_AOC_REQ 30 +#define FAC_OPVAL_AOC_S_CUR 31 +#define FAC_OPVAL_AOC_S_SPC 32 +#define FAC_OPVAL_AOC_D_CUR 33 +#define FAC_OPVAL_AOC_D_UNIT 34 +#define FAC_OPVAL_AOC_E_CUR 35 +#define FAC_OPVAL_AOC_E_UNIT 36 +#define FAC_OPVAL_AOC_IDOFCRG 37 + +#define FAC_OPVAL_CONF_BEG 40 +#define FAC_OPVAL_CONF_ADD 41 +#define FAC_OPVAL_CONF_SPLIT 42 +#define FAC_OPVAL_CONF_DROP 43 +#define FAC_OPVAL_CONF_ISOLATE 44 +#define FAC_OPVAL_CONF_REATT 45 +#define FAC_OPVAL_CONF_PDISC 46 +#define FAC_OPVAL_CONF_FCONF 47 +#define FAC_OPVAL_CONF_END 48 +#define FAC_OPVAL_CONF_IDCFE 49 + +#define FAC_OPVAL_REVC_REQ 60 + +enum states { + ST_EXP_COMP_TYP, + ST_EXP_INV_ID, + ST_EXP_OP_VAL, + ST_EXP_INFO, + ST_EXP_RUL, + ST_EXP_RU, + ST_EXP_RNOU, + ST_EXP_TOCI, + ST_EXP_DBID, + + ST_EXP_RR_INV_ID, + ST_EXP_RR_OP_VAL, + ST_EXP_RR_RESULT, + + ST_EXP_NIX +}; + +/* EOF */ + diff --git a/usr.sbin/i4b/isdndecode/isdndecode.8 b/usr.sbin/i4b/isdndecode/isdndecode.8 new file mode 100644 index 0000000..8594686 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/isdndecode.8 @@ -0,0 +1,190 @@ +.\" +.\" Copyright (c) 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdndecode.8,v 1.3 1998/12/18 17:09:38 hm Exp $ +.\" +.\" last edit-date: [Fri Dec 18 18:11:31 1998] +.\" +.\" -hm writing manual page +.\" +.Dd September 17, 1998 +.Dt isdndecode 8 +.Sh NAME +.Nm isdndecode +.Nd isdn4bsd ISDN protocol decode utility +.Sh SYNOPSIS +.Nm isdndecode +.Op Fl a +.Op Fl b +.Op Fl d +.Op Fl f Ar filename +.Op Fl h +.Op Fl i +.Op Fl l +.Op Fl o +.Op Fl p Ar filename +.Op Fl u Ar number +.Op Fl B +.Op Fl P +.Op Fl R Ar unit +.Op Fl T Ar unit +.Sh DESCRIPTION +.Nm isdndecode +is part of the isdn4bsd package and is used to provide the user with a +detailed mnemonic display of the layers 1, 2 and 3 protocol activities on +the D channel and hex dump of the B channel(s) activities. +.Pp +Together with two passive supported cards and an easy to build cable it can +also be used to monitor the complete traffic on a S0 bus providing S0 bus +analyzer features. +.Pp +The +.Nm +utility is only available for passive supported cards. +.Pp +The following options can be used: +.Bl -tag -width Ds + +.It Fl a +Run +.Nm +in analyzer mode by using two passive cards and a custom cable which can +be build as described in the file +.Em cable.txt +in the isdn4bsd source distribution. One card acts as a receiver for the +transmitting direction on the S0 bus while the other card acts as a receiver +for the receiving direction on the S0 bus. Complete traffic monitoring is +possible using this setup. + +.It Fl b +switch B channel tracing on (default off). + +.It Fl d +switch D channel tracing off (default on). + +.It Fl f +Use +.Ar filename +as the name of a file into which to write tracing output (default filename is +isdndecode<n> where n is the number of the unit to decode). + +.It Fl h +switch display of header off (default on). + +.It Fl i +print layer 1 (I.430) INFO signals to monitor layer 1 activity (default off). + +.It Fl l +switch displaying of Layer 2 (Q.921) frames off (default on). + +.It Fl o +switch off writing decode output to a file (default on). + +.It Fl p +Use +.Ar filename +as the name of a file used for the -B and -P options (default filename +is isdntracebin<n> where n is the number of the unit to decode). + +.It Fl u +Use +.Ar number +as the unit number of the controller card to decode (default 0). + +.It Fl B +Write undecoded binary decode data to a file for later or remote +analyzing (default off). + +.It Fl P +Read undecoded binary decode data from file instead from device (default off). + +.It Fl R +Use +.Ar unit +as the receiving interface unit number in analyze mode. + +.It Fl T +Use +.Ar unit +as the transmitting interface unit number in analyze mode. + +.Pp +When the USR1 signal is sent to a +.Nm +process, the currently used logfiles are reopened, so that logfile +rotation becomes possible. +.Pp +The decode output should be obvious. It is very handy to have the following +standard texts available when tracing ISDN protocols: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar I.430 +ISDN BRI layer 1 protocol description. +.It Ar Q.921 +ISDN D-channel layer 2 protocol description. +.It Ar Q.931 +ISDN D-channel layer 3 protocol description. +.El +.Pp + +.Sh FILES +.Bl -tag -width daddeldi -compact +.It Pa /dev/i4btrc<n> +The devicefile(s) used to get the decode messages for ISDN card unit <n> +out of the kernel. +.El + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +isdndecode -f /var/tmp/isdn.decode +.Ed +.Pp +will start D channel tracing on passive controller 0 with all except B +channel tracing enabled and logs everything into the output file +/tmp/isdn.decode. + +.Sh SEE ALSO +.Xr isdnd 8 + +.Sh BUGS +Still one left. + +.Sh STANDARDS +ITU Recommendations I.430, Q.920, Q.921, Q.930, Q.931 +.Pp +ITU Recommendation Q.932 (03/93), Q.950 (03/93) +.Pp +ETSI Recommendation ETS 300 179 (10/92), ETS 300 180 (10/92) +.Pp +ETSI Recommendation ETS 300 181 (04/93), ETS 300 182 (04/93) +.Pp +ITU Recommendation X.208, X.209 + +.Sh AUTHOR +The +.Nm +utility and this manual page was written by Hellmuth Michaelis, +he can be reached at hm@kts.org. + diff --git a/usr.sbin/i4b/isdndecode/layer1.c b/usr.sbin/i4b/isdndecode/layer1.c new file mode 100644 index 0000000..8dee4b7 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/layer1.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * layer1.c - isdndecode, decode and print layer 1 information + * ----------------------------------------------------------- + * + * $Id: layer1.c,v 1.2 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:11:55 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" + +/*---------------------------------------------------------------------------* + * decode layer 1 information + *---------------------------------------------------------------------------*/ +void +layer1(char *buffer, unsigned char *buf) +{ + switch(*buf) + { + case INFO0: + strcpy(buffer,"L1 INFO0 (No Signal)\n"); + break; + + case INFO1_8: + strcpy(buffer,"L1 INFO1 (Activation Request, Priority = 8)\n"); + break; + + case INFO1_10: + strcpy(buffer,"L1 INFO1 (Activation Request, Priority = 10)\n"); + break; + + case INFO2: + strcpy(buffer,"L1 INFO2 (Pending Activation)\n"); + break; + + case INFO3: + strcpy(buffer,"L1 INFO3 (Synchronized)\n"); + break; + + case INFO4_8: + strcpy(buffer,"L1 INFO4 (Activated, Priority = 8/9)\n"); + break; + + case INFO4_10: + strcpy(buffer,"L1 INFO4 (Activated, Priority = 10/11)\n"); + break; + + default: + sprintf(buffer,"L1 ERROR, invalid INFO value 0x%x!\n", *buf); + break; + } +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/layer2.c b/usr.sbin/i4b/isdndecode/layer2.c new file mode 100644 index 0000000..b7997dd --- /dev/null +++ b/usr.sbin/i4b/isdndecode/layer2.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * layer2.c - decode and print layer 2 (Q.921) information + * ------------------------------------------------------- + * + * $Id: layer2.c,v 1.3 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:12:09 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" + +/*---------------------------------------------------------------------------* + * decode poll bit + *---------------------------------------------------------------------------*/ +static void +poll(int layer, char *buffer, int cnt, unsigned char value, unsigned char mask) +{ + sprintline(layer, buffer, cnt, value, mask, "P/F, Poll = %s", (value & mask) ? "Immediate Response Required" : "No Immediate Response Required"); +} + +/*---------------------------------------------------------------------------* + * decode final bit + *---------------------------------------------------------------------------*/ +static void +final(int layer, char *buffer, int cnt, unsigned char value, unsigned char mask) +{ + sprintline(layer, buffer, cnt, value, mask, "P/F, Final = %s", (value & mask) ? "Result of Poll" : "No Result of Poll"); +} + +/*---------------------------------------------------------------------------* + * decode protocol specified in Q.921 + *---------------------------------------------------------------------------*/ +int +layer2(char *pbuf, unsigned char *buf, int dir, int printit) +{ + int sap, tei, cmd; + int cnt = 0; + char locbuf[32000]; + char *lbufp = &locbuf[0]; + char buffer[80]; + + *lbufp = '\0'; + *pbuf = '\0'; + + /* address high */ + + sap = (buf[0] >> 2) & 0x3f; + + if(sap == 0) + strcpy(buffer, "Call Control"); + else if((sap >= 1) && (sap <= 15)) + strcpy(buffer, "Reserved"); + else if(sap == 16) + strcpy(buffer, "X.25"); + else if((sap >= 17) && (sap <= 31)) + strcpy(buffer, "Reserved"); + else if(sap == 63) + strcpy(buffer, "Layer 2 Management"); + else + strcpy(buffer, "Not available for Q.921"); + sprintline(2, lbufp+strlen(lbufp), cnt, buf[0], 0xfc, "SAPI = %d (%s)", sap, buffer); + + if(dir == FROM_TE) + cmd = !(buf[0] & 0x02); + else + cmd = buf[0] & 0x02; + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[0], 0x02, "C/R = %s", cmd ? "Command" : "Response"); + extension(2, lbufp+strlen(lbufp), cnt, buf[0], 0x01); + cnt++; + + /* address low */ + + tei = buf[1] >> 1; + + if((tei >= 0) && (tei <= 63)) + strcpy(buffer, "Non-automatic TEI"); + else if((tei >= 64) && (tei <= 126)) + strcpy(buffer, "Automatic TEI"); + if(tei == 127) + strcpy(buffer, "Group TEI"); + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[1], 0xfe, "TEI = %d (%s)", tei, buffer); + extension(2, lbufp+strlen(lbufp), cnt, buf[1], 0x01); + cnt++; + + /* control 1 */ + + if((buf[2] & 0x03) == 0x03) + { + /* U-frame */ + + if((buf[2] & 0xef) == 0x6f) + { + /* SABME */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: SABME (Set Asynchonous Balanced Mode)"); + poll(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + else if((buf[2] & 0xef) == 0x0f) + { + /* DM */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: DM (Disconnected Mode)"); + final(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + else if((buf[2] & 0xef) == 0x03) + { + /* UI */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: UI (Unnumbered Information)"); + poll(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + + if(sap == 63 && (buf[3] == 0x0f)) /* TEI management */ + { + sprintline(2, lbufp+strlen(lbufp), cnt, buf[3], 0xff, "MEI (Management Entity Identifier)"); + cnt++; + sprintline(2, lbufp+strlen(lbufp), cnt, buf[4], 0xff, "Ri = 0x%04x (Reference number high)", (buf[4] << 8) | buf[5]); + cnt++; + sprintline(2, lbufp+strlen(lbufp), cnt, buf[5], 0xff, "Ri (Reference Number low)"); + cnt++; + + switch(buf[6]) + { + case 0x01: + strcpy(buffer, "Identity Request"); + break; + case 0x02: + strcpy(buffer, "Identity Assigned"); + break; + case 0x03: + strcpy(buffer, "Identity denied"); + break; + case 0x04: + strcpy(buffer, "Identity Check Request"); + break; + case 0x05: + strcpy(buffer, "Identity Check Response"); + break; + case 0x06: + strcpy(buffer, "Identity Remove"); + break; + case 0x07: + strcpy(buffer, "Identity Verify"); + break; + default: + strcpy(buffer, "undefined"); + break; + } + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[6], 0xff, "TEI %s (Message Type %d)", buffer, buf[6]); + cnt++; + + switch(buf[6]) + { + case 0x01: + strcpy(buffer, "Any TEI value acceptable"); + break; + case 0x02: + strcpy(buffer, ""); + break; + case 0x03: + strcpy(buffer, "No TEI Value available"); + break; + case 0x04: + strcpy(buffer, "Check all TEI values"); + break; + case 0x05: + strcpy(buffer, ""); + break; + case 0x06: + strcpy(buffer, "Request for removal of all TEI values"); + break; + case 0x07: + strcpy(buffer, ""); + break; + default: + strcpy(buffer, ""); + break; + } + if(((buf[7] >> 1) & 0x7f) == 127) + sprintline(2, lbufp+strlen(lbufp), cnt, buf[7], 0xfe, "Ai = %d (Action Indicator = %s)", (buf[7] >> 1) & 0x7f, buffer); + else + sprintline(2, lbufp+strlen(lbufp), cnt, buf[7], 0xfe, "Ai = %d (Action Indicator)", (buf[7] >> 1) & 0x7f); + extension(2, lbufp+strlen(lbufp), cnt, buf[7], 0x01); + cnt++; + } + } + else if((buf[2] & 0xef) == 0x43) + { + /* DISC */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: DISC (Disconnect)"); + poll(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + else if((buf[2] & 0xef) == 0x63) + { + /* UA */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: UA (Unnumbered Acknowledge)"); + final(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + else if((buf[2] & 0xef) == 0x87) + { + /* FRMR */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: FRMR (Frame Reject)"); + final(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + else if((buf[2] & 0xef) == 0x9f) + { + /* XID */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xef, "U-Frame: XID (Exchange Identification)"); + if(cmd) + poll(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + else + final(2, lbufp+strlen(lbufp), cnt, buf[2], 0x10); + cnt++; + } + + } + else if((buf[2] & 0x03) == 0x01) + { + /* S-frame */ + + if(buf[2] == 0x01) + strcpy(buffer, "RR (Receiver Ready)"); + else if(buf[2] == 0x05) + strcpy(buffer, "RNR (Receiver Not Ready)"); + else if(buf[2] == 0x09) + strcpy(buffer, "REJ (Reject)"); + else + strcpy(buffer, "Unknown"); + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xff, "S-Frame: %s", buffer); + cnt++; + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[3], 0xfe, "N(R) = %d (receive sequence number)", (buf[3] >> 1) & 0x7f); + if(cmd) + poll(2, lbufp+strlen(lbufp), cnt, buf[3], 0x01); + else + final(2, lbufp+strlen(lbufp), cnt, buf[3], 0x01); + cnt++; + + } + else if((buf[2] & 0x01) == 0x00) + { + /* I-frame */ + + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0xfe, "N(S) = %d (send sequence number)", (buf[2] >> 1) & 0x7f); + sprintline(2, lbufp+strlen(lbufp), cnt, buf[2], 0x01, "I-Frame: Information transfer"); + cnt++; + + sprintf(buffer, "N(R) = %d", (buf[3] >> 1) & 0x7f); + sprintline(2, lbufp+strlen(lbufp), cnt, buf[3], 0xfe, "N(R) = %d (receive sequence number)", (buf[3] >> 1) & 0x7f); + poll(2, lbufp+strlen(lbufp), cnt, buf[3], 0x01); + cnt++; + + } + + sprintf((pbuf+strlen(pbuf)),"%s", &locbuf[0]); + return (cnt); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/layer3.c b/usr.sbin/i4b/isdndecode/layer3.c new file mode 100644 index 0000000..6376a13 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/layer3.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * layer3.c - decode and print layer 3 (Q.931) information + * ------------------------------------------------------- + * + * $Id: layer3.c,v 1.5 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:12:21 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" + +char *mttab[] = { + +/* 0x00 */ /* call establishment group */ + + "ESCAPE", + "ALERTING", + "CALL PROCEEDING", + "PROGRESS", + "undefined (0x04)", + "SETUP", + "undefined (0x06)", + "CONNECT", + "undefined (0x08)", + "undefined (0x09)", + "undefined (0x0a)", + "undefined (0x0b)", + "undefined (0x0c)", + "SETUP ACKNOWLEDGE", + "undefined (0x0e)", + "CONNECT ACKNOWLEDGE", + +/* 0x10 */ + "undefined (0x10)", + "undefined (0x11)", + "undefined (0x12)", + "undefined (0x13)", + "undefined (0x14)", + "undefined (0x15)", + "undefined (0x16)", + "undefined (0x17)", + "undefined (0x18)", + "undefined (0x19)", + "undefined (0x1a)", + "undefined (0x1b)", + "undefined (0x1c)", + "undefined (0x1d)", + "undefined (0x1e)", + "undefined (0x1f)", + +/* 0x20 */ + + "USER INFORMATION", /* call information phase */ + "SUSPEND REJECT", + "RESUME REJECT", + "undefined (0x23)", + "HOLD", + "SUSPEND", + "RESUME", + "undefined (0x27)", + "HOLD ACKNOWLEDGE", + "undefined (0x29)", + "undefined (0x2a)", + "undefined (0x2b)", + "undefined (0x2c)", + "SUSPEND ACKNOWLEDGE", + "RESUME ACKNOWLEDGE", + "undefined (0x2f)", + +/* 0x30 */ + + "HOLD REJECT", + "RETRIEVE", + "undefined (0x32)", + "RETRIEVE ACKNOWLEDGE", + "undefined (0x34)", + "undefined (0x35)", + "undefined (0x36)", + "RETRIEVE REJECT", + "undefined (0x38)", + "undefined (0x39)", + "undefined (0x3a)", + "undefined (0x3b)", + "undefined (0x3c)", + "undefined (0x3d)", + "undefined (0x3e)", + "undefined (0x3f)", + +/* 0x40 */ + + "DETACH", /* call clearing */ + "undefined (0x41)", + "undefined (0x42)", + "undefined (0x43)", + "undefined (0x44)", + "DISCONNECT", + "RESTART", + "undefined (0x47)", + "DETACH ACKNOWLEDGE", + "undefined (0x49)", + "undefined (0x4a)", + "undefined (0x4b)", + "undefined (0x4c)", + "RELEASE", + "RESTART ACKNOWLEDGE", + "undefined (0x4f)", + +/* 0x50 */ + + "undefined (0x50)", + "undefined (0x51)", + "undefined (0x52)", + "undefined (0x53)", + "undefined (0x54)", + "undefined (0x55)", + "undefined (0x56)", + "undefined (0x57)", + "undefined (0x58)", + "undefined (0x59)", + "RELEASE COMPLETE", + "undefined (0x5b)", + "undefined (0x5c)", + "undefined (0x5d)", + "undefined (0x5e)", + "undefined (0x5f)", + +/* 0x60 */ + + "SEGMENT", /* misc messages */ + "undefined (0x61)", + "FACILITY", + "undefined (0x63)", + "REGISTER", + "undefined (0x65)", + "undefined (0x66)", + "undefined (0x67)", + "CANCEL ACKNOWLEDGE", + "undefined (0x69)", + "FACILITY ACKNOWLEDGE", + "undefined (0x6b)", + "REGISTER ACKNOWLEDGE", + "undefined (0x6d)", + "NOTIFY", + "undefined (0x6f)", + +/* 0x70 */ + + "CANCEL REJECT", + "undefined (0x71)", + "FACILITY REJECT", + "undefined (0x73)", + "REGISTER REJECT", + "STATUS ENQIRY", + "undefined (0x76)", + "undefined (0x77)", + "undefined (0x78)", + "CONGESTION CONTROL", + "undefined (0x7a)", + "INFORMATION", + "undefined (0x7c)", + "STATUS", + "undefined (0x7e)", + "undefined (0x7f)", +}; + +#define MTTAB_MAX 0x7f + +extern int f_null(char *pbuf, unsigned char *buf, int off); +extern int f_bc(char *pbuf, unsigned char *buf, int off); +extern int f_cause(char *pbuf, unsigned char *buf, int off); +extern int f_cstat(char *pbuf, unsigned char *buf, int off); +extern int f_chid(char *pbuf, unsigned char *buf, int off); +extern int f_fac(char *pbuf, unsigned char *buf, int off); +extern int f_progi(char *pbuf, unsigned char *buf, int off); +extern int f_displ(char *pbuf, unsigned char *buf, int off); +extern int f_date(char *pbuf, unsigned char *buf, int off); +extern int f_cnu(char *pbuf, unsigned char *buf, int off); +extern int f_cgpn(char *pbuf, unsigned char *buf, int off); +extern int f_cdpn(char *pbuf, unsigned char *buf, int off); +extern int f_hlc(char *pbuf, unsigned char *buf, int off); + +struct ie { + unsigned char code; /* information element identifier code */ + char *name; /* ie name */ + int (*func) (char *pbuf, unsigned char *buf, int off); /* decode function */ +} ietab[] = { + { 0x00, "segmented message", f_null }, + { 0x04, "bearer capability", f_bc }, + { 0x08, "cause", f_cause }, + { 0x0c, "connected address", f_null }, + { 0x0d, "extended facility", f_null }, + { 0x10, "call identity", f_null }, + { 0x14, "call state", f_cstat }, + { 0x18, "channel id", f_chid }, + { 0x19, "data link connection id", f_null }, + { 0x1c, "facility", f_fac }, + { 0x1e, "progress indicator", f_progi }, + { 0x20, "network specific facilities", f_null }, + { 0x24, "terminal capabilities", f_null }, + { 0x27, "notification indicator", f_null }, + { 0x28, "display", f_displ }, + { 0x29, "date/time", f_date }, + { 0x2c, "keypad", f_null }, + { 0x30, "keypad echo", f_null }, + { 0x32, "information request", f_null }, + { 0x34, "signal", f_null }, + { 0x36, "switchhook", f_null }, + { 0x38, "feature activation", f_null }, + { 0x39, "feature indication", f_null }, + { 0x3a, "service profile id", f_null }, + { 0x3b, "endpoint identifier", f_null }, + { 0x40, "information rate", f_null }, + { 0x41, "precedence level", f_null }, + { 0x42, "end-to-end transit delay", f_null }, + { 0x43, "transit delay detection", f_null }, + { 0x44, "packet layer binary parms", f_null }, + { 0x45, "packet layer window size", f_null }, + { 0x46, "packet size", f_null }, + { 0x47, "closed user group", f_null }, + { 0x48, "link layer core parameters", f_null }, + { 0x49, "link layer protocol parms", f_null }, + { 0x4a, "reverse charging information", f_null }, + { 0x4c, "connected number", f_cnu }, + { 0x4d, "connected subaddress", f_null }, + { 0x50, "X.213 priority", f_null }, + { 0x51, "report type", f_null }, + { 0x53, "link integrity verification", f_null }, + { 0x57, "PVC status", f_null }, + { 0x6c, "calling party number", f_cnu }, + { 0x6d, "calling party subaddress", f_null }, + { 0x70, "called party number", f_cnu }, + { 0x71, "called party subaddress", f_null }, + { 0x74, "redirecting number", f_null }, + { 0x78, "transit network selection", f_null }, + { 0x79, "restart indicator", f_null }, + { 0x7c, "low layer compatibility", f_null }, + { 0x7d, "high layer compatibility", f_hlc }, + { 0x7e, "user-user", f_null }, + { 0x7f, "escape for extension", f_null }, + { 0xff, "unknown information element", f_null } +}; + +/*---------------------------------------------------------------------------* + * decode Q.931 protocol + *---------------------------------------------------------------------------*/ +void +layer3(char *pbuf, int n, int off, unsigned char *buf) +{ + char buffer[256]; + int codeset = 0; + int codelock = 0; + int oldcodeset = 0; + + int pd; + int len; + int j; + int i; + + if(n <= 0) + return; + + *pbuf = '\0'; + + i = 0; + + /* protocol discriminator */ + + pd = buf[i]; + + if(pd >= 0x00 && pd <= 0x07) + sprintf(buffer, "User-User IE (0x%02x)",pd); + else if(pd == 0x08) + sprintf(buffer, "Q.931/I.451"); + else if(pd >= 0x10 && pd <= 0x3f) + sprintf(buffer, "Other Layer 3 or X.25 (0x%02x)",pd); + else if(pd >= 0x40 && pd <= 0x4f) + sprintf(buffer, "National Use (0x%02x)",pd); + else if(pd >= 0x50 && pd <= 0xfe) + sprintf(buffer, "Other Layer 3 or X.25 (0x%02x)",pd); + else + sprintf(buffer, "Reserved (0x%02x)",pd); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, pd, 0xff, "Protocol discriminator = %s", buffer); + i++; + + /* call reference */ + + len = buf[i] & 0x0f; + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xf0, "Call Reference"); + + switch(len) + { + case 0: + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 0 (Dummy CR)"); + break; + case 1: + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 1"); + i++; + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Call Reference sent %s origination side", (buf[i] & 0x80) ? "to" : "from"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Call Reference = %d = 0x%02x", (buf[i] & 0x7f), (buf[i] & 0x7f)); + break; + case 2: + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Length of Call Reference = 2"); + i++; + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Call Reference sent %s origination side", (buf[i] & 0x80) ? "to" : "from"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Call reference = %d = %02x", (buf[i] & 0x7f)); + i++; + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Call reference = %d = %02x", (buf[i])); + break; + } + i++; + + /* message type */ + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "Message type extension = %d", buf[i] & 0x80 ? 1 : 0); + + if(buf[i] <= MTTAB_MAX) + strcpy(buffer, mttab[buf[i]]); + else + sprintf(buffer, "unknown (0x%02x)", buf[i]); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Message type = %s", buffer); + i++; + + /* information elements */ + + for (; i < n;) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x80, "%s Information element", buf[i] & 0x80 ? "Single octet" : "Variable length"); + + if(buf[i] & 0x80) + { + /* single octett info element type 1 */ + + if((buf[i] & 0x70) == 0x00) + { + strcpy(buffer, "Reserved"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Reserved"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Reserved, content of IE"); + } + else if((buf[i] & 0x70) == 0x10) + { + strcpy(buffer, "Shift"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Shift"); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x08, "%s shift", buf[i] & 0x08 ? "Non-locking" : "Locking"); + + switch(buf[i] & 0x07) + { + case 0: + strcpy(buffer, "Not applicable"); + break; + case 1: + case 2: + case 3: + sprintf(buffer, "Reserved (%d)", buf[i] & 0x07); + break; + case 4: + strcpy(buffer, "Codeset 4 (ISO/IEC)"); + break; + case 5: + strcpy(buffer, "Codeset 5 (National use)"); + break; + case 6: + strcpy(buffer, "Codeset 6 (Local network specific)"); + break; + case 7: + strcpy(buffer, "Codeset 7 (User specific)"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x07, "%s", buffer); + break; + } + else if((buf[i] & 0x70) == 0x30) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Congestion Level"); + switch(buf[i] & 0x0f) + { + case 0x00: + strcpy(buffer, "receiver ready"); + break; + case 0x0f: + strcpy(buffer, "receiver not ready"); + break; + default: + sprintf(buffer, "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Congestion Level = ", buffer); + break; + } + else if((buf[i] & 0x70) == 0x50) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x70, "Repeat Indicator"); + switch(buf[i] & 0x0f) + { + case 0x02: + strcpy(buffer, "Prioritized list for selecting one possibility"); + break; + default: + sprintf(buffer, "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Repeat indication = ", buffer); + break; + } + + /* single octett info element type 2 */ + + else if((buf[i] & 0x7f) == 0x20) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "More data"); + } + else if((buf[i] & 0x7f) == 0x21) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Sending complete"); + } + else + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "UNKNOWN single octet IE = 0x%02x", buf[i]); + } + i++; /* next */ + } + else + { + if(codeset == 0) + { + struct ie *iep = &ietab[0]; + + for(;;) + { + if((iep->code == buf[i]) || + (iep->code == 0xff)) + break; + iep++; + } + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "IE = %s", iep->name); + sprintline(3, pbuf+strlen(pbuf), off+i+1, buf[i+1], 0xff, "IE Length = %d", buf[i+1]); + + if(iep->func == f_null) + { + } + else + { + i += (iep->func)(pbuf, &buf[i], off+i); + goto next; + } + } + else + { + sprintf((pbuf+strlen(pbuf)), "UNKNOWN CODESET=%d, IE=0x%02x", codeset, buf[i]); + } + + i++; /* index -> length */ + + len = buf[i]; + + sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len); + + i++; /* index -> 1st param */ + + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]); + } + + sprintf((pbuf+strlen(pbuf)),"]"); + + i += len; + +next: + + if(!codelock && (codeset != oldcodeset)) + codeset = oldcodeset; + } + } +/* sprintf((pbuf+strlen(pbuf)),"\n"); */ +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdndecode/layer3_subr.c b/usr.sbin/i4b/isdndecode/layer3_subr.c new file mode 100644 index 0000000..e1480b6 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/layer3_subr.c @@ -0,0 +1,1045 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * layer3_subr.c - subroutines for IE decoding + * ------------------------------------------- + * + * $Id: layer3_subr.c,v 1.4 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:12:37 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" + +/*---------------------------------------------------------------------------* + * dummy function + *---------------------------------------------------------------------------*/ +int +f_null(char *pbuf, unsigned char *buf, int off) +{ + return(0); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_cstat(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int len = 0; + char buffer[256]; + + i++; + len = buf[i]; + i++; + sprintf((pbuf+strlen(pbuf)), "Std="); + switch((buf[i] & 0x60) >> 5) + { + case 0: + strcpy(buffer, "CCITT"); + break; + case 1: + strcpy(buffer, "ISO/IEC"); + break; + case 2: + strcpy(buffer, "National"); + break; + case 3: + strcpy(buffer, "Special"); + break; + } + sprintf((pbuf+strlen(pbuf)), ", State="); + + switch((buf[i] & 0x3f)) + { + case 0: + strcpy(buffer, "Null"); + break; + case 1: + strcpy(buffer, "Call initiated"); + break; + case 2: + strcpy(buffer, "Overlap sending"); + break; + case 3: + strcpy(buffer, "Outgoing call proceeding"); + break; + case 4: + strcpy(buffer, "Call delivered"); + break; + case 6: + strcpy(buffer, "Call present"); + break; + case 7: + strcpy(buffer, "Call received"); + break; + case 8: + strcpy(buffer, "Connect request"); + break; + case 9: + strcpy(buffer, "Incoming call proceeding"); + break; + case 10: + strcpy(buffer, "Active"); + break; + case 11: + strcpy(buffer, "Disconnect request"); + break; + case 12: + strcpy(buffer, "Disconnect indication"); + break; + case 15: + strcpy(buffer, "Suspend request"); + break; + case 17: + strcpy(buffer, "Resume request"); + break; + case 19: + strcpy(buffer, "Release request"); + break; + case 22: + strcpy(buffer, "Call abort"); + break; + case 25: + strcpy(buffer, "Overlap receiving"); + break; + case 0x3d: + strcpy(buffer, "Restart request"); + break; + case 0x3e: + strcpy(buffer, "Restart"); + break; + default: + strcpy(buffer, "ERROR: undefined/reserved"); + break; + } + sprintf((pbuf+strlen(pbuf)), "]"); + i++; + return(i); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_chid(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int len = 0; + char buffer[256]; + + i++; + len = buf[i]; + i++; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x40, "Interface Id present = %s", buf[i] & 0x40 ? "Yes" : "No"); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x20, "Interface Type = %s", buf[i] & 0x20 ? "Other (PRI)" : "BRI"); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x10, "Spare"); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x08, "Channel = %s", buf[i] & 0x08 ? "exclusive" : "preferred"); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x04, "Channel is%s the D-Channel", buf[i] & 0x04 ? "" : " not"); + + switch(buf[i] & 0x03) + { + case 0: + strcpy(buffer, "no channel"); + break; + case 1: + strcpy(buffer, "B-1"); + break; + case 2: + strcpy(buffer, "B-2"); + break; + case 3: + strcpy(buffer, "any channel"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x03, "Channel = %s", buffer); + + i++; + return(i); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_fac(char *pbuf, unsigned char *buf, int off) +{ + return(q932_facility(pbuf, buf)); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_progi(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int len = 0; + char buffer[256]; + + i++; + len = buf[i]; + i++; + sprintf((pbuf+strlen(pbuf)), "Std="); + switch((buf[i] & 0x60) >> 5) + { + case 0: + strcpy(buffer, "CCITT"); + break; + case 1: + strcpy(buffer, "ISO/IEC"); + break; + case 2: + strcpy(buffer, "National"); + break; + case 3: + strcpy(buffer, "Local"); + break; + } + sprintf((pbuf+strlen(pbuf)), ", Loc="); + + switch((buf[i] & 0x0f)) + { + case 0: + strcpy(buffer, "User"); + break; + case 1: + strcpy(buffer, "Private network serving local user"); + break; + case 2: + strcpy(buffer, "Public network serving local user"); + break; + case 3: + strcpy(buffer, "Transit network"); + break; + case 4: + strcpy(buffer, "Public network serving remote user"); + break; + case 5: + strcpy(buffer, "Private network serving remote user"); + break; + case 6: + strcpy(buffer, "Network beyond interworking point"); + break; + default: + strcpy(buffer, "ERROR: undefined/reserved"); + break; + } + + i++; + + sprintf((pbuf+strlen(pbuf)), "\n Description"); + + switch((buf[i] & 0x7f)) + { + case 1: + strcpy(buffer, "Call is not end-to-end ISDN"); + break; + case 2: + strcpy(buffer, "Destination address is non-ISDN"); + break; + case 3: + strcpy(buffer, "Origination address is non-ISDN"); + break; + case 4: + strcpy(buffer, "Call has returned to the ISDN"); + break; + case 5: + strcpy(buffer, "Interworking occured, Service change"); + break; + case 8: + strcpy(buffer, "In-band info or appropriate pattern now available"); + break; + default: + strcpy(buffer, "ERROR: undefined/reserved"); + break; + } + sprintf((pbuf+strlen(pbuf)), "]"); + i++; + + return(i); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_displ(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int j = 0; + int len = 0; + + i++; + len = buf[i]; + i++; + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]); + } + sprintf((pbuf+strlen(pbuf)),"]"); + i += j; + + return(i); +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +int +f_date(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int j = 0; + int len = 0; + + i++; + len = buf[i]; + i++; + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Year = %02d", buf[i]); + i++; + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Month = %02d", buf[i]); + i++; + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Day = %02d", buf[i]); + i++; + + j=3; + if(j < len) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Hour = %02d", buf[i]); + i++; + j++; + } + if(j < len) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Minute = %02d", buf[i]); + i++; + j++; + } + if(j < len) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0xff, "Second = %02d", buf[i]); + i++; + j++; + } + i += len; + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the cause + *---------------------------------------------------------------------------*/ +int +f_cause(char *pbuf, unsigned char *buf, int off) +{ + int j; + int len; + int i = 0; + int ls; + char buffer[256]; + + i++; /* index -> length */ + + len = buf[i]; + + i++; /* coding/location */ + len--; + + ls = buf[i]; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((ls & 0x60) >> 5) + { + case 0: + strcpy(buffer, "CCITT"); + break; + case 1: + strcpy(buffer, "ISO/IEC"); + break; + case 2: + strcpy(buffer, "National"); + break; + case 3: + strcpy(buffer, "Local"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Coding Standard = %s", buffer); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x10, "Spare"); + + switch(ls & 0x0f) + { + case 0x00: + strcpy(buffer, "user"); + break; + case 0x01: + strcpy(buffer, "private network serving local user"); + break; + case 0x02: + strcpy(buffer, "public network serving local user"); + break; + case 0x03: + strcpy(buffer, "transit network"); + break; + case 0x04: + strcpy(buffer, "public network serving remote user"); + break; + case 0x05: + strcpy(buffer, "private network serving remote user"); + break; + case 0x07: + strcpy(buffer, "international network"); + break; + case 0x0a: + strcpy(buffer, "network beyond interworking point"); + break; + default: + sprintf(buffer, "reserved (0x%02x)", ls & 0x0f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Location = %s", buffer); + + i++; + len--; + + if(!(ls & 0x80)) + { + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch(buf[i] & 0x7f) + { + case 0: + strcpy(buffer, "Q.931"); + break; + case 3: + strcpy(buffer, "X.21"); + break; + case 4: + strcpy(buffer, "X.25"); + break; + case 5: + strcpy(buffer, "Q.1031/Q.1051"); + break; + default: + strcpy(buffer, "Reserved"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Recommendation = %s", buffer); + i++; + len--; + } + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Cause = %s", print_cause_q850(buf[i] & 0x7f)); + + i++; + len--; + + for(j = 0; j < len; j++) + sprintline(3, (pbuf+strlen(pbuf)), off+i+j, buf[i+j], 0xff, "Diagnostics = %02d %s", buf[i+j]); + + i += (len+1); + + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the bearer capability + *---------------------------------------------------------------------------*/ +int +f_bc(char *pbuf, unsigned char *buf, int off) +{ + int len; + int i = 0; + int mr = 0; + char buffer[256]; + + i++; /* index -> length */ + + len = buf[i]; + i++; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + strcpy(buffer, "CCITT"); + break; + case 1: + strcpy(buffer, "ISO/IEC"); + break; + case 2: + strcpy(buffer, "National"); + break; + case 3: + strcpy(buffer, "NSI Std"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Coding standard = %s", buffer); + + switch(buf[i] & 0x1f) + { + case 0x00: + strcpy(buffer, "speech"); + break; + case 0x08: + strcpy(buffer, "unrestricted digital information"); + break; + case 0x09: + strcpy(buffer, "restricted digital information"); + break; + case 0x10: + strcpy(buffer, "3.1 kHz audio"); + break; + case 0x11: + strcpy(buffer, "unrestricted digital information with tones"); + break; + case 0x18: + strcpy(buffer, "video"); + break; + default: + sprintf(buffer, "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x1f, "Capability = %s", buffer); + + i++; + len--; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + strcpy(buffer, "circuit"); + break; + case 2: + strcpy(buffer, "packet"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", ((buf[i] & 0x60) >> 5)); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Mode = %s", buffer); + + switch(buf[i] & 0x1f) + { + case 0x00: + strcpy(buffer, "packet mode"); + break; + case 0x10: + strcpy(buffer, "64 kbit/s"); + break; + case 0x11: + strcpy(buffer, "2 x 64 kbit/s"); + break; + case 0x13: + strcpy(buffer, "384 kbit/s"); + break; + case 0x15: + strcpy(buffer, "1536 kbit/s"); + break; + case 0x17: + strcpy(buffer, "1920 kbit/s"); + break; + case 0x18: + strcpy(buffer, "Multirate"); + mr = 1; + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x1f, "Rate = %s", buffer); + + i++; + len--; + + if(!len) + goto exit; + + if(mr) + { + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Rate multiplier = %d", buf[i] & 0x7f); + i++; + len--; + } + + if(!len) + goto exit; + + sprintf((pbuf+strlen(pbuf)), "\n layer1="); + + switch(buf[i] & 0x1f) + { + case 0x01: + sprintf((pbuf+strlen(pbuf)), "V.110"); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "G.711 u-law"); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "G.711 A-law"); + break; + case 0x04: + sprintf((pbuf+strlen(pbuf)), "G.721"); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "H.221/H.242"); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "Non-Std"); + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "V.120"); + break; + case 0x09: + sprintf((pbuf+strlen(pbuf)), "X.31"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + i++; + len--; + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n user rate=0x%02x ", buf[i] & 0x1f); + + if(buf[i] & 0x40) + sprintf((pbuf+strlen(pbuf)), "(async,"); + else + sprintf((pbuf+strlen(pbuf)), "(sync,"); + + if(buf[i] & 0x20) + sprintf((pbuf+strlen(pbuf)), "in-band neg. possible)"); + else + sprintf((pbuf+strlen(pbuf)), "in-band neg not possible)"); + + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n clk/flow=0x%02x", buf[i] & 0x1f); + + sprintf((pbuf+strlen(pbuf)), "\n intermediate rate="); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "not used"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "8 kbit/s"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "16 kbit/s"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "32 kbit/s"); + break; + } + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n hdr/mfrm/etc.=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n stop/data/parity=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n modemtype=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + switch(buf[i] & 0x7f) + { + case 0x42: + sprintf((pbuf+strlen(pbuf)), "\n layer2=Q.921/I.441"); + break; + case 0x46: + sprintf((pbuf+strlen(pbuf)), "\n layer2=X.25 link"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "\n layer2=0x%02x",(buf[i] & 0x7f)); + break; + } + i++; + len--; + + if(!len) + goto exit; + + switch(buf[i] & 0x7f) + { + case 0x62: + sprintf((pbuf+strlen(pbuf)), "\n layer3=Q.921/I.441"); + break; + case 0x66: + sprintf((pbuf+strlen(pbuf)), "\n layer3=X.25 packet"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "\n layer3=0x%02x",(buf[i] & 0x7f)); + break; + } + i++; + len--; + +exit: + + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the ISDN (telephone) number + *---------------------------------------------------------------------------*/ +int +f_cnu(char *pbuf, unsigned char *buf, int off) +{ + int j; + int len; + int i = 0; + int tp; + int ind = 0; + char buffer[256]; + + i++; /* index -> length */ + len = buf[i]; + + i++; /* index -> type/plan */ + tp = buf[i]; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((tp & 0x70) >> 4) + { + case 0: + strcpy(buffer, "Unknown"); + break; + case 1: + strcpy(buffer, "International number"); + break; + case 2: + strcpy(buffer, "National number"); + break; + case 3: + strcpy(buffer, "Network specific number"); + break; + case 4: + strcpy(buffer, "Subscriber number"); + break; + case 6: + strcpy(buffer, "Abbreviated number"); + break; + default: + sprintf(buffer, "Reserved (%d), ", ((tp & 0x70) >> 4)); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Type = %s", buffer); + + switch(tp & 0x0f) + { + case 0: + strcpy(buffer, "Unknown"); + break; + case 1: + strcpy(buffer, "ISDN (E.164)"); + break; + case 3: + strcpy(buffer, "Data (X.121)"); + break; + case 4: + strcpy(buffer, "Telex (F.69)"); + break; + case 8: + strcpy(buffer, "National"); + break; + case 9: + strcpy(buffer, "Private"); + break; + default: + sprintf(buffer, "Reserved (%d)", (tp & 0x0f)); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x0f, "Plan = %s", buffer); + + i++; + len--; + + if(!(tp & 0x80)) + { + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + strcpy(buffer, "allowed"); + break; + case 1: + strcpy(buffer, "restricted"); + break; + case 2: + strcpy(buffer, "number not available"); + break; + case 3: + strcpy(buffer, "reserved"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Presentation = %s", buffer); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x1c, "Spare"); + + switch(ind & 0x03) + { + case 0: + strcpy(buffer, "user provided, not screened"); + break; + case 1: + strcpy(buffer, "user provided, verified & passed"); + break; + case 2: + strcpy(buffer, "user provided, verified & failed"); + break; + case 3: + strcpy(buffer, "network provided"); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x03, "Screening = %s", buffer); + i++; + len--; + } + + for(j = 0; j < len; j++) + { + sprintline(3, (pbuf+strlen(pbuf)), off+i+j, buf[i+j], 0xff, "Number digit = %c", buf[i+j]); + } + + i += j; + + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print HL comatibility + *---------------------------------------------------------------------------*/ +int +f_hlc(char *pbuf, unsigned char *buf, int off) +{ + int i = 0; + int len = 0; + char buffer[256]; + + i++; + len = buf[i]; + + i++; + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch((buf[i] >> 5) & 0x03) + { + case 0: strcpy(buffer, "CCITT"); + break; + case 1: strcpy(buffer, "ISO/IEC"); + break; + case 2: strcpy(buffer, "National"); + break; + case 3: strcpy(buffer, "Network"); + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x60, "Coding standard = %s", buffer); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x1c, "Interpretation = %s", ((buf[i] >> 2) & 0x07) == 0x04 ? "first" : "reserved"); + + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x03, "Presentation = %s", ((buf[i]) & 0x03) == 0x01 ? "High layer protocol profile" : "reserved"); + + i++; + len--; + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch(buf[i] & 0x7f) + { + case 0x01: + strcpy(buffer, "Telephony"); + break; + case 0x04: + strcpy(buffer, "Fax Group 2/3 (F.182)"); + break; + case 0x21: + strcpy(buffer, "Fax Group 4 I (F.184)"); + break; + case 0x24: + strcpy(buffer, "Teletex (F.230) or Fax Group 4 II/III (F.184)"); + break; + case 0x28: + strcpy(buffer, "Teletex (F.220)"); + break; + case 0x31: + strcpy(buffer, "Teletex (F.200)"); + break; + case 0x32: + strcpy(buffer, "Videotex (F.300/T.102)"); + break; + case 0x33: + strcpy(buffer, "Videotex (F.300/T.101)"); + break; + case 0x35: + strcpy(buffer, "Telex (F.60)"); + break; + case 0x38: + strcpy(buffer, "MHS (X.400)"); + break; + case 0x41: + strcpy(buffer, "OSI (X.200)"); + break; + case 0x5e: + strcpy(buffer, "Maintenance"); + break; + case 0x5f: + strcpy(buffer, "Management"); + break; + case 0x60: + strcpy(buffer, "Audio visual (F.721)"); + break; + default: + sprintf(buffer, "Reserved (0x%02x)", buf[i] & 0x7f); + break; + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Characteristics = %s", buffer); + i++; + len--; + + if(buf[i-1] & 0x80) + { + return(i); + } + + extension(3, pbuf+strlen(pbuf), off+i, buf[i], 0x80); + + switch(buf[i] & 0x7f) + { + case 0x01: + strcpy(buffer, "Telephony"); + break; + case 0x04: + strcpy(buffer, "Fax Group 2/3 (F.182)"); + break; + case 0x21: + strcpy(buffer, "Fax Group 4 I (F.184)"); + break; + case 0x24: + strcpy(buffer, "Teletex (F.230) or Fax Group 4 II/III (F.184)"); + break; + case 0x28: + strcpy(buffer, "Teletex (F.220)"); + break; + case 0x31: + strcpy(buffer, "Teletex (F.200)"); + break; + case 0x32: + strcpy(buffer, "Videotex (F.300/T.102)"); + break; + case 0x33: + strcpy(buffer, "Videotex (F.300/T.101)"); + break; + case 0x35: + strcpy(buffer, "Telex (F.60)"); + break; + case 0x38: + strcpy(buffer, "MHS (X.400)"); + break; + case 0x41: + strcpy(buffer, "OSI (X.200)"); + break; + case 0x5e: + strcpy(buffer, "Maintenance"); + break; + case 0x5f: + strcpy(buffer, "Management"); + break; + case 0x60: + strcpy(buffer, "Audio visual (F.721)"); + break; + default: + sprintf(buffer, "Reserved (0x%02x)", buf[i] & 0x7f); + break; + + } + sprintline(3, (pbuf+strlen(pbuf)), off+i, buf[i], 0x7f, "Ext. characteristics = %s", buffer); + i++; + return(i); +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdndecode/main.c b/usr.sbin/i4b/isdndecode/main.c new file mode 100644 index 0000000..a73d708 --- /dev/null +++ b/usr.sbin/i4b/isdndecode/main.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * main.c - isdndecode main program file + * ------------------------------------- + * + * $Id: main.c,v 1.6 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:12:52 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" + +unsigned char buf[BSIZE]; +FILE *Fout = NULL; +FILE *BP = NULL; +int outflag = 1; +int header = 1; +int print_q921 = 1; +int unit = 0; +int dchan = 0; +int bchan = 0; +int traceon = 0; +int analyze = 0; +int Rx = RxUDEF; +int Tx = TxUDEF; +int f; +int Bopt = 0; +int Popt = 0; +int bpopt = 0; +int info = 0; + +static char outfilename[1024]; +static char BPfilename[1024]; + +static void dumpbuf( int n, unsigned char *buf, i4b_trace_hdr_t *hdr); +static int switch_driver( int value, int rx, int tx ); +static void usage( void ); +static void exit_hdl( void ); +static void reopenfiles( int ); + +/*---------------------------------------------------------------------------* + * main + *---------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + extern int optind; + extern int opterr; + extern char *optarg; + char devicename[80]; + char headerbuf[256]; + + int n; + int c; + char *b; + + int enable_trace = TRACE_D_RX | TRACE_D_TX; + char *outfile = DECODE_FILE_NAME; + char *binfile = BIN_FILE_NAME; + int outfileset = 0; + time_t tm; + + i4b_trace_hdr_t *ithp = NULL; + int l; + + b = &buf[sizeof(i4b_trace_hdr_t)]; + + while( (c = getopt(argc, argv, "abdf:hiln:op:u:BPR:T:?")) != EOF) + { + switch(c) + { + case 'a': + analyze = 1; + break; + + case 'b': + enable_trace |= (TRACE_B_RX | TRACE_B_TX); + break; + + case 'd': + enable_trace &= (~(TRACE_D_TX | TRACE_D_RX)); + break; + + case 'o': + outflag = 0; + break; + + case 'f': + outfile = optarg; + outfileset = 1; + break; + + case 'h': + header = 0; + break; + + case 'i': + enable_trace |= TRACE_I; + info = 1; + break; + + case 'l': + print_q921 = 0; + break; + + case 'p': + binfile = optarg; + bpopt = 1; + break; + + case 'u': + unit = atoi(optarg); + if(unit < 0 || unit >= MAX_CONTROLLERS) + usage(); + break; + + case 'B': + Bopt = 1; + break; + + case 'P': + Popt = 1; + break; + + case 'R': + Rx = atoi(optarg); + if(Rx < 0 || Rx >= MAX_CONTROLLERS) + usage(); + break; + + case 'T': + Tx = atoi(optarg); + if(Tx < 0 || Tx >= MAX_CONTROLLERS) + usage(); + break; + + case '?': + default: + usage(); + break; + } + } + + if(enable_trace == 0) + usage(); + + if(Bopt && Popt) + usage(); + + atexit(exit_hdl); + + if(Bopt) + { + if(bpopt) + sprintf(BPfilename, "%s", binfile); + else + sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit); + + if((BP = fopen(BPfilename, "r")) != NULL) + { + char buffer[1024]; + fclose(BP); + sprintf(buffer, "%s%s", BPfilename, DECODE_FILE_NAME_BAK); + rename(BPfilename, buffer); + } + if((BP = fopen(BPfilename, "w")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting file [%s] to unbuffered", BPfilename); + perror(buffer); + exit(1); + } + } + + if(Popt) + { + if(bpopt) + sprintf(BPfilename, "%s", binfile); + else + sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit); + + if((BP = fopen(BPfilename, "r")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + else + { + sprintf(devicename, "%s%d", I4BTRC_DEVICE, unit); + + if((f = open(devicename, O_RDWR)) < 0) + { + char buffer[80]; + + sprintf(buffer, "Error opening trace device [%s]", devicename); + perror(buffer); + exit(1); + } + } + + if(outflag) + { + if(outfileset == 0) + sprintf(outfilename, "%s%d", DECODE_FILE_NAME, unit); + else + strcpy(outfilename, outfile); + + + if((Fout = fopen(outfilename, "r")) != NULL) + { + char buffer[1024]; + fclose(Fout); + sprintf(buffer, "%s%s", outfilename, DECODE_FILE_NAME_BAK); + rename(outfilename, buffer); + } + + if((Fout = fopen(outfilename, "w")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", outfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting file [%s] to unbuffered", outfile); + perror(buffer); + exit(1); + } + } + + if((setvbuf(stdout, (char *)NULL, _IOLBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting stdout to line-buffered"); + perror(buffer); + exit(1); + } + + if(!Popt) + { + if((switch_driver(enable_trace, Rx, Tx)) == -1) + exit(1); + else + traceon = 1; + } + + signal(SIGHUP, SIG_IGN); /* ignore hangup signal */ + signal(SIGUSR1, reopenfiles); /* rotate logfile(s) */ + + time(&tm); + + if(analyze) + { + sprintf(headerbuf, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s", + Rx, Tx, ctime(&tm)); + } + else + { + sprintf(headerbuf, "\n=========== isdntrace controller #%d =========== started %s", + unit, ctime(&tm)); + } + + printf("%s", headerbuf); + + if(outflag) + fprintf(Fout, "%s", headerbuf); + + for (;;) + { + if(Popt == 0) + { + n = read(f, buf, BSIZE); + + if(Bopt) + { + if((fwrite(buf, 1, n, BP)) != n) + { + char buffer[80]; + sprintf(buffer, "Error writing file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + + n -= sizeof(i4b_trace_hdr_t); + } + else + { + if((fread(buf, 1, sizeof(i4b_trace_hdr_t), BP)) != sizeof(i4b_trace_hdr_t)) + { + if(feof(BP)) + { + printf("\nEnd of playback input file reached.\n"); + exit(0); + } + else + { + char buffer[80]; + sprintf(buffer, "Error reading hdr from file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + + ithp = (i4b_trace_hdr_t *)buf; + l = ithp->length - sizeof(i4b_trace_hdr_t); + + if((n = fread(buf+sizeof(i4b_trace_hdr_t), 1, l , BP)) != l) + { + char buffer[80]; + sprintf(buffer, "Error reading data from file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + } + + if(n > 0) + { + dumpbuf(n, b, (i4b_trace_hdr_t *)buf); + } + } +} + +/*---------------------------------------------------------------------------* + * format header into static buffer, return buffer address + *---------------------------------------------------------------------------*/ +char * +fmt_hdr(i4b_trace_hdr_t *hdr, int frm_len) +{ + struct tm *s; + static char hbuf[256]; + int i = 0; + + s = localtime(&(hdr->time.tv_sec)); + + if(hdr->type == TRC_CH_I) /* Layer 1 INFO's */ + { + sprintf(hbuf,"\n-- %s - unit:%d ---------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec); + } + else + { + if(hdr->trunc > 0) + { + sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d (%d) ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + hdr->count, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec, + frm_len, + hdr->trunc); + } + else + { + sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%06u - length:%d ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + hdr->count, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec, + frm_len); + } + } + + for(i=strlen(hbuf); i <= NCOLS;) + hbuf[i++] = '-'; + + hbuf[i++] = '\n'; + hbuf[i] = '\0'; + + return(hbuf); +} + +/*---------------------------------------------------------------------------* + * decode protocol and output to file(s) + *---------------------------------------------------------------------------*/ +static void +dumpbuf(int n, unsigned char *buf, i4b_trace_hdr_t *hdr) +{ + static char l1buf[128]; + static unsigned char l2buf[32000]; + static unsigned char l3buf[32000]; + int cnt; + int nsave = n; + char *pbuf; + int i, j; + + l1buf[0] = '\0'; + l2buf[0] = '\0'; + l3buf[0] = '\0'; + + switch(hdr->type) + { + case TRC_CH_I: /* Layer 1 INFO's */ + layer1(l1buf, buf); + break; + + case TRC_CH_D: /* D-channel data */ + cnt = layer2(l2buf, buf, hdr->dir, print_q921); + + n -= cnt; + buf += cnt; + + if(n) + layer3(l3buf, n, cnt, buf); + break; + + default: /* B-channel data */ + + pbuf = &l2buf[0]; + + for (i = 0; i < n; i += 16) + { + sprintf((pbuf+strlen(pbuf)),"B%d:%.3x ", hdr->type, i); + + for (j = 0; j < 16; j++) + if (i + j < n) + sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf))," "); + + sprintf((pbuf+strlen(pbuf))," "); + + for (j = 0; j < 16 && i + j < n; j++) + if (isprint(buf[i + j])) + sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf)),"."); + + sprintf((pbuf+strlen(pbuf)),"\n"); + } + break; + } + + if(header && ((l1buf[0] != '\0' || l2buf[0] != '\0') || (l3buf[0] != 0))) + { + char *p; + p = fmt_hdr(hdr, nsave); + printf("%s", p); + if(outflag) + fprintf(Fout, "%s", p); + } + + if(l1buf[0] != '\0') + { + printf("%s", l1buf); + if(outflag) + fprintf(Fout, "%s", l1buf); + } + + if(l2buf[0] != '\0') + { + printf("%s", l2buf); + if(outflag) + fprintf(Fout, "%s", l2buf); + } + + if(l3buf[0] != '\0') + { + printf("%s", l3buf); + if(outflag) + fprintf(Fout, "%s", l3buf); + } +} + +/*---------------------------------------------------------------------------* + * exit handler function to be called at program exit + *---------------------------------------------------------------------------*/ +void +exit_hdl() +{ + if(traceon) + switch_driver(TRACE_OFF, Rx, Tx); +} + +/*---------------------------------------------------------------------------* + * switch driver debugging output on/off + *---------------------------------------------------------------------------*/ +static int +switch_driver(int value, int rx, int tx) +{ + char buffer[80]; + int v = value; + + if(analyze == 0) + { + if(ioctl(f, I4B_TRC_SET, &v) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_SET, val = %d", v); + perror(buffer); + return(-1); + } + } + else + { + if(value == TRACE_OFF) + { + if(ioctl(f, I4B_TRC_RESETA, &v) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_RESETA - "); + perror(buffer); + return(-1); + } + } + else + { + i4b_trace_setupa_t tsa; + + tsa.rxunit = rx; + tsa.rxflags = value; + tsa.txunit = tx; + tsa.txflags = value; + + if(ioctl(f, I4B_TRC_SETA, &tsa) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_SETA, val = %d", v); + perror(buffer); + return(-1); + } + } + } + return(0); +} + +/*---------------------------------------------------------------------------* + * reopen files to support rotating logfile(s) on SIGUSR1 + * + * based on an idea from Ripley (ripley@nostromo.in-berlin.de) + * + * close file and reopen it for append. this will be a nop + * if the previously opened file hasn't moved but will open + * a new one otherwise, thus enabling a rotation... + * + *---------------------------------------------------------------------------*/ +static void +reopenfiles(int dummy) +{ + if(outflag) + { + fclose(Fout); + + if((Fout = fopen(outfilename, "a")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error re-opening file [%s]", outfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error re-setting file [%s] to unbuffered", outfilename); + perror(buffer); + exit(1); + } + } + + if(Bopt) + { + + fclose(BP); + + if((BP = fopen(BPfilename, "a")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error re-opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error re-setting file [%s] to unbuffered", BPfilename); + perror(buffer); + exit(1); + } + } +} + +/*---------------------------------------------------------------------------* + * decode extension bit + *---------------------------------------------------------------------------*/ +void +extension(int layer, char *buffer, int cnt, unsigned char value, unsigned char mask) +{ + sprintline(layer, buffer, cnt, value, mask, "Extension Bit = %c (%s)", + (value & mask) ? '1' : '0', + (value & mask) ? "no extension, final octet" : "with extension, octet follows"); +} + +/*---------------------------------------------------------------------------* + * print bits as 0/1 available for mask + *---------------------------------------------------------------------------*/ +static char * +print_bits(unsigned char val, unsigned char mask) +{ + static char buffer[10]; + int i = 0; + int length = 8; + + while(length--) + { + if(mask & 0x80) + { + if(val & 0x80) + buffer[i++] = '1'; + else + buffer[i++] = '0'; + } + else + { + buffer[i++] = '-'; + } + val = val << 1; + mask = mask << 1; + } + buffer[i] = '\0'; + return(buffer); +} + +/*---------------------------------------------------------------------------* + * print one decoded output line + *---------------------------------------------------------------------------*/ +void +sprintline(int layer, char *buffer, int oct_count, int oct_val, + int oct_mask, const char *fmt, ...) +{ + char lbuffer[256]; + static int lastcount = -1; + char *ptr; + va_list ap; + + va_start(ap, fmt); + + if(oct_count != lastcount) + { + lastcount = oct_count; + + sprintf(lbuffer, "L%d %2d %02X %s ", + layer, + oct_count, + oct_val, + print_bits(oct_val, oct_mask)); + } + else + { + sprintf(lbuffer, " %s ", + print_bits(oct_val, oct_mask)); + } + + vsprintf(lbuffer+strlen(lbuffer), fmt, ap); + + va_end(ap); + + sprintf(lbuffer+strlen(lbuffer), "\n"); + + if((ptr = rindex(lbuffer, '(')) != NULL) + { + char *s = lbuffer; + char *b = buffer; + int len = strlen(lbuffer); + int i; + + for(s = lbuffer; s < ptr; *b++ = *s++) + ; + for(i = 0;(i+len) <= NCOLS; *b++ = ' ', i++) + ; + for(; *s; *b++ = *s++) + ; + *b = '\0'; + } + else + { + strcpy(buffer, lbuffer); + } +} + +/*---------------------------------------------------------------------------* + * usage intructions + *---------------------------------------------------------------------------*/ +void +usage(void) +{ + fprintf(stderr,"\n"); + fprintf(stderr,"isdndecode - isdn4bsd package ISDN decoder for passive cards (%02d.%02d)\n", VERSION, REL); + fprintf(stderr,"usage: isdntrace -a -b -d -f <file> -h -i -l -n <val> -o -p <file> -r -u <unit>\n"); + fprintf(stderr," -B -P -R <unit> -T <unit>\n"); + fprintf(stderr," -a analyzer mode ................................... (default off)\n"); + fprintf(stderr," -b switch B channel trace on ....................... (default off)\n"); + fprintf(stderr," -d switch D channel trace off ....................... (default on)\n"); + fprintf(stderr," -f <file> write output to file filename ............ (default %s0)\n", DECODE_FILE_NAME); + fprintf(stderr," -h don't print header for each message ............. (default off)\n"); + fprintf(stderr," -i print I.430 (layer 1) INFO signals .............. (default off)\n"); + fprintf(stderr," -l don't decode low layer Q.921 messages ........... (default off)\n"); + fprintf(stderr," -o don't write output to a file .................... (default off)\n"); + fprintf(stderr," -p <file> specify filename for -B and -P ........ (default %s0)\n", BIN_FILE_NAME); + fprintf(stderr," -u <unit> specify controller unit number ............... (default unit 0)\n"); + fprintf(stderr," -B write binary trace data to file filename ........ (default off)\n"); + fprintf(stderr," -P playback from binary trace data file ............ (default off)\n"); + fprintf(stderr," -R <unit> analyze Rx controller unit number (for -a) ... (default unit %d)\n", RxUDEF); + fprintf(stderr," -T <unit> analyze Tx controller unit number (for -a) ... (default unit %d)\n", TxUDEF); + fprintf(stderr,"\n"); + exit(1); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/pcause.c b/usr.sbin/i4b/isdndecode/pcause.c new file mode 100644 index 0000000..9c5535e --- /dev/null +++ b/usr.sbin/i4b/isdndecode/pcause.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcause.c - printing cause values + * -------------------------------- + * + * $Id: pcause.c,v 1.3 1998/12/23 10:03:55 hm Exp $ + * + * last edit-date: [Wed Dec 23 10:59:54 1998] + * + *---------------------------------------------------------------------------*/ + +#include "decode.h" +#include "pcause.h" + +char * +print_cause_q850(unsigned char code) +{ + static char error_message[120]; + char *e; + + switch(code) + { + case CAUSE_Q850_SHUTDN: + e = "normal D-channel shutdown"; + break; + + case CAUSE_Q850_NUNALLC: + e = "Unallocated (unassigned) number"; + break; + + case CAUSE_Q850_NRTTN: + e = "No route to specified transit network"; + break; + + case CAUSE_Q850_NRTDST: + e = "No route to destination"; + break; + + case CAUSE_Q850_SSINFTN: + e = "Send special information tone"; + break; + + case CAUSE_Q850_MDIALTP: + e = "Misdialled trunk prefix"; + break; + + case CAUSE_Q850_CHUNACC: + e = "Channel unacceptable"; + break; + + case CAUSE_Q850_CALLAWD: + e = "Call awarded and being delivered in an established channel"; + break; + + case CAUSE_Q850_PREEMPT: + e = "Preemption"; + break; + + case CAUSE_Q850_PREECRR: + e = "Preemption - circuit reserved for reuse"; + break; + + case CAUSE_Q850_NCCLR: + e = "Normal call clearing"; + break; + + case CAUSE_Q850_USRBSY: + e = "User busy"; + break; + + case CAUSE_Q850_NOUSRRSP: + e = "No user responding"; + break; + + case CAUSE_Q850_NOANSWR: + e = "No answer from user (user alerted)"; + break; + + case CAUSE_Q850_SUBSABS: + e = "Subscriber absent"; + break; + + case CAUSE_Q850_CALLREJ: + e = "Call rejected"; + break; + + case CAUSE_Q850_NUCHNG: + e = "Number changed"; + break; + + case CAUSE_Q850_NONSELUC: + e = "Non-selected user clearing"; + break; + + case CAUSE_Q850_DSTOOORDR: + e = "Destination out of order"; + break; + + case CAUSE_Q850_INVNUFMT: + e = "Invalid number format"; + break; + + case CAUSE_Q850_FACREJ: + e = "Facility rejected"; + break; + + case CAUSE_Q850_STENQRSP: + e = "Response to STATUS ENQUIRY"; + break; + + case CAUSE_Q850_NORMUNSP: + e = "Normal, unspecified"; + break; + + case CAUSE_Q850_NOCAVAIL: + e = "No circuit / channel available"; + break; + + case CAUSE_Q850_NETOOORDR: + e = "Network out of order"; + break; + + case CAUSE_Q850_PFMCDOOSERV: + e = "Permanent frame mode connection out of service"; + break; + + case CAUSE_Q850_PFMCOPER: + e = "Permanent frame mode connection operational"; + break; + + case CAUSE_Q850_TMPFAIL: + e = "Temporary failure"; + break; + + case CAUSE_Q850_SWEQCONG: + e = "Switching equipment congestion"; + break; + + case CAUSE_Q850_ACCINFDIS: + e = "Access information discarded"; + break; + + case CAUSE_Q850_REQCNOTAV: + e = "Requested circuit/channel not available"; + break; + + case CAUSE_Q850_PRECALBLK: + e = "Precedence call blocked"; + break; + + case CAUSE_Q850_RESUNAVAIL: + e = "Resources unavailable, unspecified"; + break; + + case CAUSE_Q850_QOSUNAVAIL: + e = "Quality of service unavailable"; + break; + + case CAUSE_Q850_REQSERVNS: + e = "Requested facility not subscribed"; + break; + + case CAUSE_Q850_OCBARRCUG: + e = "Outgoing calls barred within CUG"; + break; + + case CAUSE_Q850_ICBARRCUG: + e = "Incoming calls barred within CUG"; + break; + + case CAUSE_Q850_BCAPNAUTH: + e = "Bearer capability not authorized"; + break; + + case CAUSE_Q850_BCAPNAVAIL: + e = "Bearer capability not presently available"; + break; + + case CAUSE_Q850_INCSTOACISC: + e = "Inconsistenciy in designated outg. access info and subscriber class"; + break; + + case CAUSE_Q850_SOONOTAVAIL: + e = "Service or option not available, unspecified"; + break; + + case CAUSE_Q850_BCAPNOTIMPL: + e = "Bearer capability not implemented"; + break; + + case CAUSE_Q850_CHTYPNIMPL: + e = "Channel type not implemented"; + break; + + case CAUSE_Q850_REQFACNIMPL: + e = "Requested facility not implemented"; + break; + + case CAUSE_Q850_ORDINBCAVL: + e = "Only restricted digital information bearer capability is available"; + break; + + case CAUSE_Q850_SOONOTIMPL: + e = "Service or option not implemented, unspecified"; + break; + + case CAUSE_Q850_INVCLRFVAL: + e = "Invalid call reference value"; + break; + + case CAUSE_Q850_IDCHDNOEX: + e = "Identified channel does not exist"; + break; + + case CAUSE_Q850_SUSCAEXIN: + e = "A suspended call exists, but this call identity does not"; + break; + + case CAUSE_Q850_CLIDINUSE: + e = "Call identity in use"; + break; + + case CAUSE_Q850_NOCLSUSP: + e = "No call suspended"; + break; + + case CAUSE_Q850_CLIDCLRD: + e = "Call having the requested call identity has been cleared"; + break; + + case CAUSE_Q850_UNOTMEMCUG: + e = "User not member of CUG"; + break; + + case CAUSE_Q850_INCDEST: + e = "Incompatible destination"; + break; + + case CAUSE_Q850_NONEXCUG: + e = "Non-existent CUG"; + break; + + case CAUSE_Q850_INVNTWSEL: + e = "Invalid transit network selection"; + break; + + case CAUSE_Q850_INVMSG: + e = "Invalid message, unspecified"; + break; + + case CAUSE_Q850_MIEMISS: + e = "Mandatory information element is missing"; + break; + + case CAUSE_Q850_MSGTNI: + e = "Message type non-existent or not implemented"; + break; + + case CAUSE_Q850_MSGNCMPT: + e = "Msg incompatible with call state/message type non-existent/not implemented"; + break; + + case CAUSE_Q850_IENENI: + e = "Information element/parameter non-existent or not implemented"; + break; + + case CAUSE_Q850_INVIEC: + e = "Invalid information element contents"; + break; + + case CAUSE_Q850_MSGNCWCS: + e = "Message not compatible with call state"; + break; + + case CAUSE_Q850_RECOTIMEXP: + e = "Recovery on timer expiry"; + break; + + case CAUSE_Q850_PARMNENIPO: + e = "Parameter non-existent or not implemented, passed on"; + break; + + case CAUSE_Q850_MSGUNRDPRM: + e = "Message with unrecognized parameter, discarded"; + break; + + case CAUSE_Q850_PROTERR: + e = "Protocol error, unspecified"; + break; + + case CAUSE_Q850_INTWRKU: + e = "Interworking, unspecified"; + break; + + default: + e = "ERROR, unknown cause value!"; + break; + } + + sprintf(error_message, "%d: %s (Q.850)", code, e); + return(error_message); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdndecode/pcause.h b/usr.sbin/i4b/isdndecode/pcause.h new file mode 100644 index 0000000..6b6627b --- /dev/null +++ b/usr.sbin/i4b/isdndecode/pcause.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcause.h - Q.850 causes definitions + * ----------------------------------- + * + * $Id: pcause.h,v 1.2 1998/12/18 17:09:38 hm Exp $ + * + * last edit-date: [Fri Dec 18 18:13:23 1998] + * + *---------------------------------------------------------------------------*/ + +char *print_cause_q850(unsigned char code); + +/* Q.850 causes */ + +#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */ +#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */ +#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */ +#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */ +#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */ +#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */ +#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */ +#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */ +#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */ +#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */ +#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */ +#define CAUSE_Q850_USRBSY 0x11 /* User busy */ +#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */ +#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */ +#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */ +#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */ +#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */ +#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */ +#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */ +#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */ +#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */ +#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */ +#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */ +#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */ +#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */ +#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */ +#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */ +#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */ +#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */ +#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */ +#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */ +#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */ +#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */ +#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */ +#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */ +#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */ +#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */ +#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */ +#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */ +#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */ +#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */ +#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */ +#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */ +#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */ +#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */ +#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */ +#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */ +#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */ +#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */ +#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */ +#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */ +#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */ +#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */ +#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */ +#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */ +#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */ +#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */ +#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */ +#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */ +#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */ +#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */ +#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */ +#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */ +#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */ +#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */ +#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */ +#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */ +#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdnmonitor/Makefile b/usr.sbin/i4b/isdnmonitor/Makefile new file mode 100644 index 0000000..9d3811b --- /dev/null +++ b/usr.sbin/i4b/isdnmonitor/Makefile @@ -0,0 +1,8 @@ +PROG = isdnmonitor +SRCS = main.c +MAN8 = isdnmonitor.8 + +# compile debug support +COPTS += -DDEBUG + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/isdnmonitor/isdnmonitor.8 b/usr.sbin/i4b/isdnmonitor/isdnmonitor.8 new file mode 100644 index 0000000..9bcb783 --- /dev/null +++ b/usr.sbin/i4b/isdnmonitor/isdnmonitor.8 @@ -0,0 +1,40 @@ +.\" Copyright (c) 1998 Martin Husemann <martin@rumolt.teuto.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. The name of the author may not be used to endorse or promote products +.\" derived from this software withough specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: isdnmonitor.8,v 1.2 1998/08/10 13:55:29 hm Exp $ +.\" +.\" last edit-date: [Fri Jan 30 22:49:48 1998] +.\" +.\" -mh writing manual pages +.\" +.\" +.Dd April 18, 1998 +.Dt isdnmonitor 8 +.Sh NAME +.Nm isdnmonitor +.Nd raw sample and test client for isdnd network monitoring +.Sh DESCRIPTION +The +.Nm +is not intended for real world use. It will be replaced +by something with a better user interface as soon as the monitoring +subsystem is functional. diff --git a/usr.sbin/i4b/isdnmonitor/main.c b/usr.sbin/i4b/isdnmonitor/main.c new file mode 100644 index 0000000..73ae8fe --- /dev/null +++ b/usr.sbin/i4b/isdnmonitor/main.c @@ -0,0 +1,675 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - network monitor client + * ----------------------------------- + * + * $Id: main.c,v 1.9 1998/10/27 10:54:23 hm Exp $ + * + * last edit-date: [Tue Oct 27 11:53:12 1998] + * + * -mh created + * -hm checking in + * -hm porting to HPUX + * -mh all events the fullscreen mode displays now as monitor event + * + *---------------------------------------------------------------------------*/ + + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <time.h> +#include <errno.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <sys/un.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <machine/i4b_ioctl.h> + +#ifdef __hpux +#define AF_LOCAL AF_UNIX +#endif + +#ifdef DEBUG +#include <ctype.h> +#endif + +#include "monitor.h" + +/* + * Local function prototypes + */ +static int connect_local(const char *sockpath); +static int connect_remote(const char *host, int portno); +static void usage(); +static void mloop(); +static void handle_input(); +static void print_menu(); +static void print_logevent(time_t tstamp, int prio, const char * what, const char * msg); +static void print_charge(time_t tstamp, int channel, int units, int estimated); +static void print_connect(time_t tstamp, int dir, int channel, const char * cfgname, const char * devname, const char * remphone, const char * locphone); +static void print_disconnect(time_t tstamp, int channel); +static void print_updown(time_t tstamp, int channel, int isup); +static void handle_event(BYTE *msg, int len); +#ifdef DEBUG +static void dump_event(BYTE *msg, int len); +#endif + +/* + * Global variables + */ +static int dumpall = 0; +static int monsock = -1; +static int state = 0; +static int sub_state = 0; +static int sub_state_count = 0; + +static int major = 0; +static int minor = 0; +static int nctrl = 0; +static u_int32_t rights = 0; + +/* + * Parse command line, startup monitor client + */ +int main(int argc, char **argv) +{ + char * sockpath = NULL; + char * hostname = NULL; + int portno = DEF_MONPORT; + int i; + + while ((i = getopt(argc, argv, "dh:p:l:")) != EOF) + { + switch (i) + { + case 'd': + dumpall = 1; + break; + case 'h': + hostname = optarg; + break; + case 'l': + sockpath = optarg; + break; + case 'p': + if ((sscanf(optarg, "%i", &portno)) != 1) + usage(); + break; + default: + usage(); + break; + } + } + + if (hostname && sockpath) + { + fprintf(stderr, "Error: can not use local socket path on remote machine\n" + "conflicting options -h and -l!\n"); + return 1; + } + + if (sockpath) + { + monsock = connect_local(sockpath); + } + else if (hostname) + { + monsock = connect_remote(hostname, portno); + } + else + { + usage(); + } + + if (monsock == -1) + { + fprintf(stderr, "Could not connect to i4b isdn daemon.\n"); + return 1; + } + + signal(SIGPIPE, SIG_IGN); + mloop(); + + close(monsock); + + return 0; +} + +/* + * Display usage and exit + */ +static void usage() +{ + fprintf(stderr, "usage:\n" + " isdnmonitor [-d] -h (host) -p (port)\n" + "or\n" + " isdnmonitor [-d] -l (path)\n" + "where (host) is the hostname and (port) the port number of\n" + "the isdnd to be monitored and (path) is the pathname of the\n" + "local domain socket used to communicate with a daemon on the\n" + "local machine.\n" + "Options are:\n" + " -d dump all incoming packets as hexdump\n" + ); + exit(0); +} + +/* + * Connect via tcp/ip. + * Return socket if successfull, -1 on error. + */ +static int connect_remote(const char *host, int portno) +{ + struct sockaddr_in sa; + struct hostent *h; + int remotesockfd; + + h = gethostbyname(host); + + if (!h) + { + fprintf(stderr, "could not resolve hostname '%s'\n", host); + exit(1); + } + + remotesockfd = socket(AF_INET, SOCK_STREAM, 0); + + if (remotesockfd == -1) + { + fprintf(stderr, "could not create remote monitor socket: %s\n", strerror(errno)); + exit(1); + } + + memset(&sa, 0, sizeof sa); + +#ifdef BSD4_4 + sa.sin_len = sizeof sa; +#endif + sa.sin_family = AF_INET; + sa.sin_port = htons(portno); + + memcpy(&sa.sin_addr.s_addr, h->h_addr_list[0], sizeof sa.sin_addr.s_addr); + + if (connect(remotesockfd, (struct sockaddr *)&sa, sizeof sa) == -1) + { + fprintf(stderr, "could not connect remote monitor: %s\n", strerror(errno)); + exit(1); + } + + return remotesockfd; +} + +/* + * Connect local. + * Return socket on success, -1 on failure. + */ +static int connect_local(const char *sockpath) +{ + int s; + struct sockaddr_un sa; + + /* check path length */ + if (strlen(sockpath) >= sizeof sa.sun_path) + { + fprintf(stderr, "pathname to long for local socket: %s\n", + sockpath); + exit(1); + } + + /* create and setup socket */ + s = socket(AF_LOCAL, SOCK_STREAM, 0); + + if (s == -1) + { + fprintf(stderr, "could not create local monitor socket:%s\n", strerror(errno)); + exit(1); + } + + memset(&sa, 0, sizeof sa); + +#ifndef __hpux + sa.sun_len = sizeof sa; +#endif + + sa.sun_family = AF_LOCAL; + strcpy(sa.sun_path, sockpath); + + if (connect(s, (struct sockaddr *)&sa, sizeof sa)) + { + fprintf(stderr, "could not connect local monitor socket [%s]: %s\n", sockpath, strerror(errno)); + } + + return s; +} + +/* + * main event loop + */ +static void mloop() +{ + for (;;) + { + fd_set rd, wr, ex; + + FD_ZERO(&rd); + FD_ZERO(&wr); + FD_ZERO(&ex); + FD_SET(fileno(stdin), &rd); + FD_SET(monsock, &rd); + + select(monsock+1, &rd, &wr, &ex, NULL); + + if (FD_ISSET(fileno(stdin), &rd)) + { + handle_input(); + } + + if (FD_ISSET(monsock, &rd)) + { + BYTE buf[1024]; + u_long u; + int bytes, ret; + + /* Network transfer may deliver two or more packets concatenated. + * Peek at the header and read only one event at a time... */ + + ioctl(monsock, FIONREAD, &u); + + if (u < I4B_MON_EVNT_HDR) + continue; /* not enough data there yet */ + + bytes = recv(monsock, buf, I4B_MON_EVNT_HDR, MSG_PEEK); + + if (bytes < I4B_MON_EVNT_HDR) + continue; /* errh? something must be wrong... */ + + bytes = I4B_GET_2B(buf, I4B_MON_EVNT_LEN); + + if (bytes >= sizeof buf) + break; + + /* now we know the size, it fits, so lets read it! */ + + ret = read(monsock, buf, bytes); + + if (ret == 0) + { + printf("remote isdnd has closed our connection\n"); + break; + } + else if (ret < 0) + { + printf("error reading from isdnd: %s", strerror(errno)); + break; + } +#ifdef DEBUG + if (dumpall) + dump_event(buf, ret); +#endif + handle_event(buf, ret); + } + } +} + +#ifdef DEBUG +/* + * Dump a complete event packet. + */ +static void dump_event(BYTE *msg, int len) +{ + int i; + + printf("event dump:"); + + for (i = 0; i < len; i++) + { + if (i % 8 == 0) + printf("\n%02x: ", i); + printf("%02x %c ", msg[i], isprint(msg[i]) ? msg[i] : '.'); + } + printf("\n"); +} +#endif + +static void print_logevent(time_t tstamp, int prio, const char * what, const char * msg) +{ + char buf[256]; + strftime(buf, sizeof buf, I4B_TIME_FORMAT, localtime(&tstamp)); + printf("log: %s prio %d what=%s msg=%s\n", + buf, prio, what, msg); +} + +static void print_charge(time_t tstamp, int channel, int units, int estimated) +{ + char buf[256]; + strftime(buf, sizeof buf, I4B_TIME_FORMAT, localtime(&tstamp)); + printf("%s: channel %d, charge = %d%s\n", + buf, channel, units, estimated ? " (estimated)" : ""); +} + +/* + * Print a connect event. + * A real monitor would allocate state info for "channel" on this + * event. + */ +static void print_connect( + time_t tstamp, /* server time of event */ + int outgoing, /* 0 = incoming, 1 = outgoing */ + int channel, /* channel no, used to identify this connection until disconnect */ + const char * cfgname, /* name of config entry/connection */ + const char * devname, /* device used (e.g. isp0) */ + const char * remphone, /* phone no of remote side */ + const char * locphone) /* local phone no */ +{ + char buf[256]; + strftime(buf, sizeof buf, I4B_TIME_FORMAT, localtime(&tstamp)); + + if (outgoing) + printf("%s: calling out to '%s' [from msn: '%s']", + buf, remphone, locphone); + else + printf("%s: incoming call from '%s' [to msn: '%s']", + buf, remphone, locphone); + printf(", channel %d, config '%s' on device '%s'\n", + channel, cfgname, devname); +} + +/* + * Print a disconnect event. + * A real monitor could free the "per connection" state + * for this channel now + */ +static void print_disconnect(time_t tstamp, int channel) +{ + char buf[256]; + strftime(buf, sizeof buf, I4B_TIME_FORMAT, localtime(&tstamp)); + printf("%s: channel %d disconnected\n", + buf, channel); +} + +/* + * Print an up- or down event + */ +static void print_updown(time_t tstamp, int channel, int isup) +{ + char buf[256]; + strftime(buf, sizeof buf, I4B_TIME_FORMAT, localtime(&tstamp)); + printf("%s: channel %d is %s\n", + buf, channel, isup ? "up" : "down"); +} + +/* + * Dispatch one message received from the daemon. + */ +static void handle_event(BYTE *msg, int len) +{ + BYTE cmd[I4B_MON_ICLIENT_SIZE]; + int local; + u_int32_t net; + u_int32_t mask; + u_int32_t who; + + switch (state) + { + case 0: /* initial data */ + + major = I4B_GET_2B(msg, I4B_MON_IDATA_VERSMAJOR); + minor = I4B_GET_2B(msg, I4B_MON_IDATA_VERSMINOR); + nctrl = I4B_GET_2B(msg, I4B_MON_IDATA_NUMCTRL); + rights = I4B_GET_4B(msg, I4B_MON_IDATA_CLACCESS); + + printf("remote protocol version is %02d.%02d, %d controller(s) found, our rights = %x\n", + major, minor, nctrl, rights); + + if (nctrl > 0) + { + state = 1; + sub_state = 0; + } + else + { + state = 2; + + /* show menu for the first time */ + print_menu(); + } + + /* set maximum event mask */ + I4B_PREP_CMD(cmd, I4B_MON_CCMD_SETMASK); + I4B_PUT_2B(cmd, I4B_MON_ICLIENT_VERMAJOR, MPROT_VERSION); + I4B_PUT_2B(cmd, I4B_MON_ICLIENT_VERMINOR, MPROT_REL); + I4B_PUT_4B(cmd, I4B_MON_ICLIENT_EVENTS, ~0U); + + write(monsock, cmd, sizeof cmd); + + break; + + case 1: /* initial controller list */ + printf("controller %d: %s\n", sub_state++, msg+I4B_MON_ICTRL_NAME); + + if (sub_state >= nctrl) + { + state = 2; /* end of list reached */ + sub_state = 0; + + /* show menu for the first time */ + print_menu(); + } + break; + + case 2: /* any event */ + + switch (I4B_GET_2B(msg, I4B_MON_EVNT)) + { + case I4B_MON_DRINI_CODE: + state = 3; /* list of rights entries will follow */ + sub_state = 0; + sub_state_count = I4B_GET_2B(msg, I4B_MON_DRINI_COUNT); + printf("monitor rights:\n"); + break; + + case I4B_MON_DCINI_CODE: + state = 4; + sub_state = 0; + sub_state_count = I4B_GET_2B(msg, I4B_MON_DCINI_COUNT); + printf("monitor connections:\n"); + break; + + case I4B_MON_LOGEVNT_CODE: + print_logevent(I4B_GET_4B(msg, I4B_MON_LOGEVNT_TSTAMP), + I4B_GET_4B(msg, I4B_MON_LOGEVNT_PRIO), + msg+I4B_MON_LOGEVNT_WHAT, + msg+I4B_MON_LOGEVNT_MSG); + break; + + case I4B_MON_CHRG_CODE: + print_charge(I4B_GET_4B(msg, I4B_MON_CHRG_TSTAMP), + I4B_GET_4B(msg, I4B_MON_CHRG_CHANNEL), + I4B_GET_4B(msg, I4B_MON_CHRG_UNITS), + I4B_GET_4B(msg, I4B_MON_CHRG_ESTIMATED)); + break; + + case I4B_MON_CONNECT_CODE: + print_connect( + I4B_GET_4B(msg, I4B_MON_CONNECT_TSTAMP), + I4B_GET_4B(msg, I4B_MON_CONNECT_DIR), + I4B_GET_4B(msg, I4B_MON_CONNECT_CHANNEL), + msg+I4B_MON_CONNECT_CFGNAME, + msg+I4B_MON_CONNECT_DEVNAME, + msg+I4B_MON_CONNECT_REMPHONE, + msg+I4B_MON_CONNECT_LOCPHONE); + break; + + case I4B_MON_DISCONNECT_CODE: + print_disconnect( + I4B_GET_4B(msg, I4B_MON_DISCONNECT_TSTAMP), + I4B_GET_4B(msg, I4B_MON_DISCONNECT_CHANNEL)); + break; + + case I4B_MON_UPDOWN_CODE: + print_updown( + I4B_GET_4B(msg, I4B_MON_UPDOWN_TSTAMP), + I4B_GET_4B(msg, I4B_MON_UPDOWN_CHANNEL), + I4B_GET_4B(msg, I4B_MON_UPDOWN_ISUP)); + break; + + default: + printf("unknown event code: %d\n", I4B_GET_2B(msg, I4B_MON_EVNT)); + } + break; + + case 3: /* one record in a list of monitor rights */ + rights = I4B_GET_4B(msg, I4B_MON_DR_RIGHTS); + net = I4B_GET_4B(msg, I4B_MON_DR_NET); + mask = I4B_GET_4B(msg, I4B_MON_DR_MASK); + local = I4B_GET_1B(msg, I4B_MON_DR_LOCAL); + + if (local) + { + printf("\tlocal: rights = %x\n", rights); + } + else + { + printf("\tfrom: %d.%d.%d.%d, mask %d.%d.%d.%d, rights = %x\n", + (net >> 24) & 0x00ff, (net >> 16) & 0x00ff, (net >> 8) & 0x00ff, net & 0x00ff, + (mask >> 24) & 0x00ff, (mask >> 16) & 0x00ff, (mask >> 8) & 0x00ff, mask & 0x00ff, + rights); + } + + sub_state++; + + if (sub_state >= sub_state_count) + { + state = 2; + print_menu(); + } + break; + + case 4: + who = I4B_GET_4B(msg, I4B_MON_DC_WHO); + rights = I4B_GET_4B(msg, I4B_MON_DC_RIGHTS); + + printf("\tfrom: %d.%d.%d.%d, rights = %x\n", + (who >> 24) & 0x00ff, (who >> 16) & 0x00ff, (who >> 8) & 0x00ff, who & 0x00ff, + rights); + + sub_state++; + + if (sub_state >= sub_state_count) + { + state = 2; + print_menu(); + } + break; + + default: + printf("unknown event from remote: local state = %d, evnt = %x, len = %d\n", + state, I4B_GET_2B(msg, I4B_MON_EVNT), len); + } +} + +/* + * Process input from user + */ +static void handle_input() +{ + char buf[1024]; + int channel; + + fgets(buf, sizeof buf, stdin); + + switch (atoi(buf)) + { + case 1: + { + BYTE cmd[I4B_MON_DUMPRIGHTS_SIZE]; + I4B_PREP_CMD(cmd, I4B_MON_DUMPRIGHTS_CODE); + write(monsock, cmd, I4B_MON_DUMPRIGHTS_SIZE); + } + break; + + case 2: + { + BYTE cmd[I4B_MON_DUMPMCONS_SIZE]; + I4B_PREP_CMD(cmd, I4B_MON_DUMPMCONS_CODE); + write(monsock, cmd, I4B_MON_DUMPMCONS_SIZE); + } + break; + + case 3: + { + BYTE cmd[I4B_MON_CFGREREAD_SIZE]; + I4B_PREP_CMD(cmd, I4B_MON_CFGREREAD_CODE); + write(monsock, cmd, I4B_MON_CFGREREAD_SIZE); + } + break; + + case 4: + { + BYTE cmd[I4B_MON_HANGUP_SIZE]; + I4B_PREP_CMD(cmd, I4B_MON_HANGUP_CODE); + printf("Which channel do you wish to hangup? "); + fgets(buf, sizeof buf, stdin); + channel = atoi(buf); + I4B_PUT_4B(cmd, I4B_MON_HANGUP_CHANNEL, channel); + write(monsock, cmd, I4B_MON_HANGUP_SIZE); + } + break; + + case 9: + close(monsock); + exit(0); + break; + + default: + print_menu(); + break; + } +} + +/* + * Display menu + */ +static void print_menu() +{ + printf("Menu: <1> display rights, <2> display monitor connections,\n"); + printf(" <3> reread config file, <4> hangup \n"); + printf(" <9> quit isdnmonitor\n"); +} diff --git a/usr.sbin/i4b/isdnmonitor/monitor.h b/usr.sbin/i4b/isdnmonitor/monitor.h new file mode 100644 index 0000000..0025449 --- /dev/null +++ b/usr.sbin/i4b/isdnmonitor/monitor.h @@ -0,0 +1,263 @@ +/* + * Copyright (c) 1998 Martin Husemann. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * i4b daemon - network monitor protocl definition + * ----------------------------------------------- + * + * $Id: monitor.h,v 1.4 1998/08/10 13:55:32 hm Exp $ + * + * last edit-date: [Mon Aug 3 06:52:06 1998] + * + * -mh created + * -hm checking in + * -hm ported to HPUX 10.10 + * + *---------------------------------------------------------------------------*/ + +#ifndef MONITOR_H +#define MONITOR_H + +#define DEF_MONPORT 451 /* default monitor TCP port */ + +#ifdef __hpux +#define u_int8_t ubit8 +#define u_int32_t ubit32 +#endif +#ifdef _WIN32 +#define u_int8_t BYTE +#define u_in32_t DWORD +#endif + +/* + * The monitor client connects to the isdnd daemon process via a tcp/ip + * connection from a remote machine or via a local (unix domain) socket. + * The daemon accepts multiple connections and verifies access rights. + * On connection establishment the daemon sends initial data telling + * the client the current configuration: number and type of available + * controllers, current connections, channel and interface states + * and the clients access privileges. The client sends an event mask + * telling the daemon which events it is interested in. If the client + * has appropriate rights he may send commands to the daemon. + * + * All multi-byte values are in network byte order! + */ + +/* All data packets transfered are declared as arrays of BYTE */ +#define BYTE u_int8_t + +/* max stringlength used in this protocol */ +#define I4B_MAX_MON_STRING 256 + +/* max command size from client to server */ +#define I4B_MAX_MON_CLIENT_CMD 16 + +/* Version of the monitor protocol described here */ +#define MPROT_VERSION 0 /* major version no */ +#define MPROT_REL 1 /* release no */ +/* + * We intend to keep different versions of monitor client and isdnd + * interoperable as long as possible. We do not, however, even try + * to do this during early alpha or beta release phases. If you run + * developement versions at this stage, make sure all your clients + * and servers run the same version! + */ + +/* + * Client access rights + */ +#define I4B_CA_COMMAND_FULL 1 /* may send any command */ +#define I4B_CA_COMMAND_RESTRICTED 2 /* may send 'harmless' commands */ +#define I4B_CA_EVNT_CHANSTATE 16 /* may watch b-channel states */ +#define I4B_CA_EVNT_CALLIN 32 /* may watch incoming calls */ +#define I4B_CA_EVNT_CALLOUT 64 /* may watch outgoing calls */ +#define I4B_CA_EVNT_I4B 128 /* may watch isdnd actions */ + +/* + * General layout of a command packet. All commands have this common + * prefix. It is prepared by the macro I4B_PREP_CMD (s.b.) + */ +#define I4B_MON_CMD 0 /* 2 byte: command code */ +#define I4B_MON_CMD_LEN 2 /* 2 byte: packet length */ +#define I4B_MON_CMD_HDR 4 /* size of header */ + +/* + * Currently events look the same as commands. We do not make + * any guarantee this will remain the same, so a different set + * of macros is used when describing events. Events are prepared + * by I4B_PREP_EVNT (s.b.) + */ +#define I4B_MON_EVNT 0 /* 2 byte: event code */ +#define I4B_MON_EVNT_LEN 2 /* 2 byte: packet length */ +#define I4B_MON_EVNT_HDR 4 /* size of header */ + +/* Initial data send by daemon after connection is established */ +#define I4B_MON_IDATA_SIZE I4B_MON_EVNT_HDR+10 +#define I4B_MON_IDATA_CODE 0 /* event code */ +#define I4B_MON_IDATA_VERSMAJOR I4B_MON_EVNT_HDR+0 /* 2 byte: isdnd major version */ +#define I4B_MON_IDATA_VERSMINOR I4B_MON_EVNT_HDR+2 /* 2 byte: isdnd minor version */ +#define I4B_MON_IDATA_NUMCTRL I4B_MON_EVNT_HDR+4 /* 2 byte: number of controllers */ +#define I4B_MON_IDATA_CLACCESS I4B_MON_EVNT_HDR+6 /* 4 byte: client rights */ + +/* followed by this for every controller */ +#define I4B_MON_ICTRL_SIZE I4B_MON_EVNT_HDR+I4B_MAX_MON_STRING+8 +#define I4B_MON_ICTRL_CODE 1 /* event code */ +#define I4B_MON_ICTRL_NAME I4B_MON_EVNT_HDR+0 /* string: name of controller */ +#define I4B_MON_ICTRL_BUSID I4B_MON_EVNT_HDR+I4B_MAX_MON_STRING+0 /* 2 byte: isdn bus id (reservered) */ +#define I4B_MON_ICTRL_FLAGS I4B_MON_EVNT_HDR+I4B_MAX_MON_STRING+2 /* 4 byte: controller flags (not yet defined) */ +#define I4B_MON_ICTRL_NCHAN I4B_MON_EVNT_HDR+I4B_MAX_MON_STRING+6 /* 2 byte: number of b channels on this controller */ + +/* The client sets it's protocol version and event mask (usualy once after + * connection establishement) */ +#define I4B_MON_CCMD_SETMASK 0x7e /* command code */ +#define I4B_MON_ICLIENT_SIZE I4B_MON_CMD_HDR+8 +#define I4B_MON_ICLIENT_VERMAJOR I4B_MON_CMD_HDR+0 /* 2 byte: protocol major version (always 0 for now) */ +#define I4B_MON_ICLIENT_VERMINOR I4B_MON_CMD_HDR+2 /* 2 byte: protocol minor version (always 0 for now) */ +#define I4B_MON_ICLIENT_EVENTS I4B_MON_CMD_HDR+4 /* 4 byte: client event mask */ + +/* The client requests a list of monitor rights */ +#define I4B_MON_DUMPRIGHTS_CODE 1 +#define I4B_MON_DUMPRIGHTS_SIZE I4B_MON_CMD_HDR /* no parameters */ + +/* in response to a I4B_MON_DUMPRIGHTS_CODE command, the daemon sends + * this event: */ +#define I4B_MON_DRINI_CODE 2 /* event code */ +#define I4B_MON_DRINI_SIZE I4B_MON_EVNT_HDR+2 /* size of packet */ +#define I4B_MON_DRINI_COUNT I4B_MON_EVNT_HDR+0 /* 2 byte: number of records */ + +/* followed by this for each record anounced above */ +#define I4B_MON_DR_CODE 3 +#define I4B_MON_DR_SIZE I4B_MON_EVNT_HDR+13 +#define I4B_MON_DR_RIGHTS I4B_MON_EVNT_HDR+0 /* 4 byte: rights mask */ +#define I4B_MON_DR_NET I4B_MON_EVNT_HDR+4 /* 4 byte: network address */ +#define I4B_MON_DR_MASK I4B_MON_EVNT_HDR+8 /* 4 byte: network mask */ +#define I4B_MON_DR_LOCAL I4B_MON_EVNT_HDR+12 /* 1 byte: non-zero if local socket */ + +/* The client requests a list of monitor connections */ +#define I4B_MON_DUMPMCONS_CODE 2 +#define I4B_MON_DUMPMCONS_SIZE I4B_MON_CMD_HDR /* no parameters */ + +/* in response to a I4B_MON_DUMPMCONS_CODE command, the daemon sends + * this event: */ +#define I4B_MON_DCINI_CODE 4 /* event code */ +#define I4B_MON_DCINI_SIZE I4B_MON_EVNT_HDR+2 /* size of packet */ +#define I4B_MON_DCINI_COUNT I4B_MON_EVNT_HDR+0 /* 2 byte: number of records */ + +/* followed by this for each record anounced above */ +#define I4B_MON_DC_CODE 5 +#define I4B_MON_DC_SIZE I4B_MON_EVNT_HDR+8 +#define I4B_MON_DC_RIGHTS I4B_MON_EVNT_HDR+0 /* 4 byte: rights mask */ +#define I4B_MON_DC_WHO I4B_MON_EVNT_HDR+4 /* 4 byte: network address */ + +/* The client requests a config file rescan */ +#define I4B_MON_CFGREREAD_CODE 3 +#define I4B_MON_CFGREREAD_SIZE I4B_MON_CMD_HDR /* no parameters */ + +/* The client requests to hangup a connection */ +#define I4B_MON_HANGUP_CODE 4 +#define I4B_MON_HANGUP_SIZE I4B_MON_CMD_HDR+4 +#define I4B_MON_HANGUP_CHANNEL I4B_MON_CMD_HDR+0 /* channel to drop */ + +/* The daemon sends a logfile event */ +#define I4B_MON_LOGEVNT_CODE 6 +#define I4B_MON_LOGEVNT_SIZE I4B_MON_EVNT_HDR+8+2*I4B_MAX_MON_STRING +#define I4B_MON_LOGEVNT_TSTAMP I4B_MON_EVNT_HDR+0 /* 4 byte: timestamp */ +#define I4B_MON_LOGEVNT_PRIO I4B_MON_EVNT_HDR+4 /* 4 byte: syslog priority */ +#define I4B_MON_LOGEVNT_WHAT I4B_MON_EVNT_HDR+8 /* followed by 2 strings: 'what' and 'message' */ +#define I4B_MON_LOGEVNT_MSG I4B_MON_EVNT_HDR+8+I4B_MAX_MON_STRING + +/* The daemon sends a charge event */ +#define I4B_MON_CHRG_CODE 7 +#define I4B_MON_CHRG_SIZE I4B_MON_EVNT_HDR+16 +#define I4B_MON_CHRG_TSTAMP I4B_MON_EVNT_HDR+0 /* 4 byte: timestamp */ +#define I4B_MON_CHRG_CHANNEL I4B_MON_EVNT_HDR+4 /* 4 byte: channel charged */ +#define I4B_MON_CHRG_UNITS I4B_MON_EVNT_HDR+8 /* 4 byte: new charge value */ +#define I4B_MON_CHRG_ESTIMATED I4B_MON_EVNT_HDR+12 /* 4 byte: 0 = charge by network, 1 = calculated estimate */ + +/* The daemon sends a connect event */ +#define I4B_MON_CONNECT_CODE 8 +#define I4B_MON_CONNECT_SIZE I4B_MON_EVNT_HDR+12+4*I4B_MAX_MON_STRING +#define I4B_MON_CONNECT_TSTAMP I4B_MON_EVNT_HDR+0 /* 4 byte: time stamp */ +#define I4B_MON_CONNECT_DIR I4B_MON_EVNT_HDR+4 /* 4 byte: direction (0 = incoming, 1 = outgoing) */ +#define I4B_MON_CONNECT_CHANNEL I4B_MON_EVNT_HDR+8 /* 4 byte: channel connected */ +#define I4B_MON_CONNECT_CFGNAME I4B_MON_EVNT_HDR+12 /* name of config entry */ +#define I4B_MON_CONNECT_DEVNAME I4B_MON_EVNT_HDR+12+I4B_MAX_MON_STRING /* name of device used for connection */ +#define I4B_MON_CONNECT_REMPHONE I4B_MON_EVNT_HDR+12+2*I4B_MAX_MON_STRING /* remote phone no. */ +#define I4B_MON_CONNECT_LOCPHONE I4B_MON_EVNT_HDR+12+3*I4B_MAX_MON_STRING /* local phone no. */ + +/* The daemon sends a disconnect event */ +#define I4B_MON_DISCONNECT_CODE 9 +#define I4B_MON_DISCONNECT_SIZE I4B_MON_EVNT_HDR+8 +#define I4B_MON_DISCONNECT_TSTAMP I4B_MON_EVNT_HDR+0 /* 4 byte: time stamp */ +#define I4B_MON_DISCONNECT_CHANNEL I4B_MON_EVNT_HDR+4 /* 4 byte: channel disconnected */ + +/* The daemon sends an up/down event */ +#define I4B_MON_UPDOWN_CODE 10 +#define I4B_MON_UPDOWN_SIZE I4B_MON_EVNT_HDR+12 +#define I4B_MON_UPDOWN_TSTAMP I4B_MON_EVNT_HDR+0 /* 4 byte: time stamp */ +#define I4B_MON_UPDOWN_CHANNEL I4B_MON_EVNT_HDR+4 /* 4 byte: channel disconnected */ +#define I4B_MON_UPDOWN_ISUP I4B_MON_EVNT_HDR+8 /* 4 byte: interface is up */ + +/* macros for setup/decoding of protocol packets */ + +/* clear a record */ +#define I4B_CLEAR(r) memset(&(r), 0, sizeof(r)); + +/* prepare a record as event or command */ +#define I4B_PREP_EVNT(r, e) { \ + I4B_CLEAR(r); \ + I4B_PUT_2B(r, I4B_MON_EVNT, e); \ + I4B_PUT_2B(r, I4B_MON_EVNT_LEN, sizeof(r)); \ +} +#define I4B_PREP_CMD(r, c) { \ + I4B_CLEAR(r); \ + I4B_PUT_2B(r, I4B_MON_CMD, c); \ + I4B_PUT_2B(r, I4B_MON_CMD_LEN, sizeof(r)); \ +} + +/* put 1, 2 or 4 bytes in network byte order into a record at offset off */ +#define I4B_PUT_1B(r, off, val) { ((BYTE*)(r))[off] = (val) & 0x00ff; } +#define I4B_PUT_2B(r, off, val) { I4B_PUT_1B(r, off, val >> 8); I4B_PUT_1B(r, off+1, val); } +#define I4B_PUT_4B(r, off, val) { I4B_PUT_1B(r, off, val >> 24); I4B_PUT_1B(r, off+1, val >> 16); I4B_PUT_1B(r, off+2, val >> 8); I4B_PUT_1B(r, off+3, val); } + +/* get 1, 2 or 4 bytes in network byte order from a record at offset off */ +#define I4B_GET_1B(r, off) (((BYTE*)(r))[off]) +#define I4B_GET_2B(r, off) ((((BYTE*)(r))[off]) << 8) | (((BYTE*)(r))[off+1]) +#define I4B_GET_4B(r, off) ((((BYTE*)(r))[off]) << 24) | ((((BYTE*)(r))[off+1]) << 16) | ((((BYTE*)(r))[off+2]) << 8) | (((BYTE*)(r))[off+3]) + +/* put a string into recor r at offset off, make sure it's not to long + * and proper terminate it */ +#define I4B_PUT_STR(r, off, str) { \ + strncpy(r+off, str, I4B_MAX_MON_STRING); \ + r[off+I4B_MAX_MON_STRING-1] = (BYTE)0; } + +#endif /* MONITOR_H */ + diff --git a/usr.sbin/i4b/isdntel/Makefile b/usr.sbin/i4b/isdntel/Makefile new file mode 100644 index 0000000..c44fc80 --- /dev/null +++ b/usr.sbin/i4b/isdntel/Makefile @@ -0,0 +1,6 @@ +PROG = isdntel +SRCS = main.c display.c files.c alias.c +LDADD += -lncurses +MAN8 = isdntel.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/isdntel/alias.c b/usr.sbin/i4b/isdntel/alias.c new file mode 100644 index 0000000..fa02ea9 --- /dev/null +++ b/usr.sbin/i4b/isdntel/alias.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntel - isdn4bsd telephone answering machine support + * ====================================================== + * + * $Id: alias.c,v 1.5 1998/12/05 18:03:51 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:15:02 1998] + * + *----------------------------------------------------------------------------*/ + +#include "defs.h" +#include "alias.h" + +static struct alias *firsta = NULL; + +#define MAXBUFSZ 256 + +/*---------------------------------------------------------------------------* + * read in and init aliases + *---------------------------------------------------------------------------*/ +void +init_alias(char *filename) +{ + FILE *fp; + char buffer[MAXBUFSZ + 1]; + char number[MAXBUFSZ + 1]; + char name[MAXBUFSZ + 1]; + char *s, *d; + struct alias *newa = NULL; + struct alias *lasta = NULL; + + if((fp = fopen(filename, "r")) == NULL) + fatal("cannot open aliasfile %s!", filename); + + while((fgets(buffer, MAXBUFSZ, fp)) != NULL) + { + if(buffer[0] == '#' || buffer[0] == ' ' || + buffer[0] == '\t' || buffer[0] == '\n') + { + continue; + } + + s = buffer; + d = number; + + while(*s && (isdigit(*s))) + *d++ = *s++; + + *d = '\0'; + + while(*s && (isspace(*s))) + s++; + + d = name; + + while(*s && (isprint(*s))) + *d++ = *s++; + + *d = '\0'; + + if((strlen(number) > 1) && (strlen(name) > 1)) + { + if((newa = (struct alias *) malloc(sizeof(struct alias))) == NULL) + fatal("malloc failed for struct alias"); + if((newa->number = (char *) malloc(strlen(number)+1)) == NULL) + fatal("malloc failed for number alias"); + if((newa->name = (char *) malloc(strlen(name)+1)) == NULL) + fatal("malloc failed for name alias"); + strcpy(newa->name, name); + strcpy(newa->number, number); + newa->next = NULL; + + if(firsta == NULL) + { + firsta = newa; + } + else + { + lasta->next = newa; + } + lasta = newa; + } + } + fclose(fp); +} + +/*---------------------------------------------------------------------------* + * read in and init aliases + *---------------------------------------------------------------------------*/ +char * +get_alias(char *number) +{ + struct alias *ca = NULL; + + if(firsta == NULL) + return(NULL); + + ca = firsta; + + for(;;) + { + if(strlen(number) == strlen(ca->number)) + { + if(!(strcmp(number, ca->number))) + return(ca->name); + } + if(ca->next == NULL) + break; + ca = ca->next; + } + return(NULL); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntel/alias.h b/usr.sbin/i4b/isdntel/alias.h new file mode 100644 index 0000000..98b91da --- /dev/null +++ b/usr.sbin/i4b/isdntel/alias.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdn4bsd common alias file handling header + * ========================================== + * + * $Id: alias.h,v 1.3 1998/12/05 18:03:52 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:15:13 1998] + * + *----------------------------------------------------------------------------*/ + +#ifndef _ALIAS_H_ +#define _ALIAS_H_ + +#define ALIASFILE "/etc/isdn/isdntel.alias" + +struct alias { + char *number; /* telephone number string */ + char *name; /* name string */ + struct alias *next; /* ptr to next alias */ +}; + +#endif /* _ALIAS_H_ */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdntel/defs.h b/usr.sbin/i4b/isdntel/defs.h new file mode 100644 index 0000000..e9233c3 --- /dev/null +++ b/usr.sbin/i4b/isdntel/defs.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntel - isdn4bsd telephone answering support + * ============================================== + * + * $Id: defs.h,v 1.6 1998/12/05 18:03:53 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:15:26 1998] + * + *----------------------------------------------------------------------------*/ + +#include <ncurses.h> +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <stdarg.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/time.h> +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 +#include <dirent.h> +#else +#include <sys/dir.h> +#endif +#include <sys/param.h> + +#define VERSION "1" /* version number */ +#define REL "11" /* release number */ + +#define GOOD 0 +#define ERROR (-1) +#define WARNING (-2) + +#define SPOOLDIR "/var/isdn" +#define PLAYCMD "cat %s | alaw2ulaw >/dev/audio" + +/* reread timeout in seconds */ + +#define REREADTIMEOUT 60 + +/* window dimensions */ + +#define START_O 3 /* main window start */ + +#define DAT_POS 0 +#define TIM_POS (DAT_POS+10) +#define DST_POS (TIM_POS+8) +#define SRC_POS (DST_POS+17) +#define ALI_POS (SRC_POS+17) +#define SEC_POS (ALI_POS+21) +#define LAST_POS (SEC_POS+5) + +/* fullscreen mode menu window */ + +#define WMITEMS 5 /* no of items */ +#define WMENU_LEN 18 /* window width */ +#define WMENU_HGT (WMITEMS+4) /* window height */ +#define WMENU_TITLE "Command" +#define WMENU_POSLN 8 /* window position: lines */ +#define WMENU_POSCO 20 /* window position: columns */ + +#define CR 0x0d +#define LF 0x0a +#define TAB 0x09 +#define CNTRL_D 0x04 +#define CNTRL_L 0x0c + +struct onefile { + char *fname; /* filename */ + char *date; + char *time; + char *srcnumber; + char *dstnumber; + char *seconds; + char *alias; + int len; + struct onefile *next; /* ptr to next entry */ + struct onefile *prev; /* prt to previous entry */ +}; + +#ifdef MAIN + +int curses_ready = 0; /* flag, curses display is initialized */ + +struct onefile *cur_file = NULL;/* the CURRENT filename */ +struct onefile *first = NULL; /* init dir-list head-ptr */ +struct onefile *last = NULL; /* init dir-list tail-ptr */ + +WINDOW *main_w; /* curses main window pointer */ + +int nofiles = 0; +int cur_pos = 0; + +char *spooldir = SPOOLDIR; +char *playstring = PLAYCMD; + +#else + +extern int curses_ready; + +extern struct onefile *cur_file; +extern struct onefile *first; +extern struct onefile *last; + +extern WINDOW *main_w; + +extern int nofiles; +extern int cur_pos; + +extern char *spooldir; +extern char *playstring; + +#endif + +extern void init_alias( char *filename ); +extern void init_files( int inipos ); +extern void init_screen ( void ); +extern void do_menu ( void ); +extern int fill_list( void ); +extern char *get_alias( char *number ); +extern int main ( int argc, char **argv ); +extern void do_quit ( int exitval ); +extern void fatal ( char *fmt, ... ); +extern void error ( char *fmt, ... ); +extern void play ( struct onefile * ); +extern void delete ( struct onefile * ); +extern void reread( void ); + +/* EOF */ diff --git a/usr.sbin/i4b/isdntel/display.c b/usr.sbin/i4b/isdntel/display.c new file mode 100644 index 0000000..1cc0034 --- /dev/null +++ b/usr.sbin/i4b/isdntel/display.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntel - isdn4bsd telephone answering machine support + * ====================================================== + * + * $Id: display.c,v 1.4 1998/12/05 18:03:55 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:15:40 1998] + * + *----------------------------------------------------------------------------*/ + +#include "defs.h" + +static char *helpstr = "Enter Control-D to exit program or RETURN for command window"; + +/*---------------------------------------------------------------------------* + * init curses fullscreen display + *---------------------------------------------------------------------------*/ +void +init_screen(void) +{ + char buffer[512]; + + initscr(); /* curses init */ + + if((COLS < 80) || (LINES < 24)) + fatal(0, "ERROR, minimal screensize must be 80x24, is %dx%d, terminating!", COLS, LINES); + + + if((main_w = newwin(LINES-START_O-2, COLS, START_O, 0)) == NULL) + fatal("ERROR, curses init main window, terminating!"); + + raw(); /* raw input */ + noecho(); /* do not echo input */ + keypad(stdscr, TRUE); /* use special keys */ + keypad(main_w, TRUE); /* use special keys */ + scrollok(main_w, TRUE); + + sprintf(buffer, " isdntel %s.%s ", VERSION, REL); + + move(0, 0); + standout(); + hline(ACS_HLINE, 5); + move(0, 5); + addstr(buffer); + move(0, 5 + strlen(buffer)); + hline(ACS_HLINE, 256); + standend(); + + move(1, 0); + addstr("Date Time Called Party Calling Party Alias Length"); + /* 31.12.96 16:45:12 1234567890123456 1234567890123456 12345678901234567890 123456 */ + + move(2, 0); + hline(ACS_HLINE, 256); + + move(LINES-2, 0); + hline(ACS_HLINE, 256); + + mvaddstr(LINES-1, (COLS / 2) - (strlen(helpstr) / 2), helpstr); + + refresh(); + + wrefresh(main_w); + + curses_ready = 1; +} + +/*---------------------------------------------------------------------------* + * curses menu for fullscreen command mode + *---------------------------------------------------------------------------*/ +void +do_menu(void) +{ + static char *menu[WMITEMS] = + { + "Play File", +#define PLAY 0 + "Delete File", +#define DELETE 1 + "Re-Read Spool", +#define REREAD 2 + "Refresh Screen", +#define REFRESH 3 + "Exit Program", +#define EXIT 4 + }; + + WINDOW *menu_w; + int c; + int mpos; + + /* create a new window in the lower screen area */ + + if((menu_w = newwin(WMENU_HGT, WMENU_LEN, WMENU_POSLN, WMENU_POSCO )) == NULL) + return; + + keypad(menu_w, TRUE); /* use special keys */ + + /* draw border around the window */ + + box(menu_w, 0, 0); + + /* add a title */ + + wstandout(menu_w); + mvwaddstr(menu_w, 0, (WMENU_LEN / 2) - (strlen(WMENU_TITLE) / 2), WMENU_TITLE); + wstandend(menu_w); + + /* fill the window with the menu options */ + + for(mpos=0; mpos <= (WMITEMS-1); mpos++) + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + + /* highlight the first menu option */ + + mpos = 0; + wstandout(menu_w); + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + wstandend(menu_w); + + /* input loop */ + + for(;;) + { + wrefresh(menu_w); + + c = wgetch(menu_w); + + switch(c) + { + case TAB: + case KEY_DOWN: /* down-move cursor */ + case ' ': + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + mpos++; + if(mpos >= WMITEMS) + mpos = 0; + wstandout(menu_w); + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + wstandend(menu_w); + break; + + case KEY_UP: /* up-move cursor */ + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + if(mpos) + mpos--; + else + mpos = WMITEMS-1; + wstandout(menu_w); + mvwaddstr(menu_w, mpos + 2, 2, menu[mpos]); + wstandend(menu_w); + break; + + case 'R': + case 'r': + wrefresh(curscr); + goto mexit; + + case 'E': + case 'e': + case 'Q': + case 'q': + case 'X': + case 'x': + do_quit(0); + goto mexit; + break; + + case 'P': + case 'p': + play(cur_file); + goto mexit; + break; + + case 'D': + case 'd': + delete(cur_file); + goto mexit; + break; + + case CR: + case LF: /* exec highlighted option */ +#ifdef KEY_ENTER + case KEY_ENTER: +#endif + switch(mpos) + { + case PLAY: + play(cur_file); + goto mexit; + break; + case DELETE: + delete(cur_file); + goto mexit; + break; + case REREAD: + reread(); + goto mexit; + break; + case REFRESH: + wrefresh(curscr); + break; + case EXIT: + do_quit(0); + break; + } + goto mexit; + break; + + default: + goto mexit; + break; + } + } + +mexit: + /* delete the menu window */ + + delwin(menu_w); + + /* re-display the original lower window contents */ + + touchwin(main_w); + wrefresh(main_w); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntel/files.c b/usr.sbin/i4b/isdntel/files.c new file mode 100644 index 0000000..ea153f5 --- /dev/null +++ b/usr.sbin/i4b/isdntel/files.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntel - isdn4bsd telephone answering machine support + * ====================================================== + * + * $Id: files.c,v 1.6 1998/12/05 18:03:56 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:15:57 1998] + * + *----------------------------------------------------------------------------*/ + +#include "defs.h" + +/*---------------------------------------------------------------------------* + * create a doubly linked list in sorted order, return pointer to new + * first element of list + *---------------------------------------------------------------------------*/ +struct onefile *store + (register struct onefile *new, /* new entry to store into list */ + register struct onefile *top) /* current first entry in list */ +{ + register struct onefile *old, *p; + + if (last == NULL) /* enter very first element ? */ + { + new->next = NULL; + new->prev = NULL; + last = new; /* init last */ + return (new); /* return new first */ + } + p = top; /* p = old first element */ + old = NULL; + while (p) + { + if ((strcmp(p->fname, new->fname)) < 0) /* current less new ? */ + { + old = p; + p = p->next; + } + else + { /* current >= new */ + + if (p->prev) + { + p->prev->next = new; + new->next = p; + new->prev = p->prev; + p->prev = new; + return (top); + } + new->next = p; + new->prev = NULL; + p->prev = new; + return (new); + } + } + old->next = new; + new->next = NULL; + new->prev = old; + last = new; + return (first); +} + +/*---------------------------------------------------------------------------* + * read current directory and build up a doubly linked sorted list + *---------------------------------------------------------------------------*/ +int +fill_list(void) +{ +#if defined(__FreeBSD__) && __FreeBSD__ >= 3 + register struct dirent *dp; +#else + register struct direct *dp; +#endif + register struct onefile *new_entry; + register DIR *dirp; + int flcnt = 0; + char tmp[80]; + char *s, *d; + + if ((dirp = opendir(spooldir)) == NULL) + fatal("cannot open spooldirectory %s!\n", spooldir); + + for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) + { + if(!isdigit(*(dp->d_name))) + continue; + + if ((new_entry = (struct onefile *) malloc(sizeof(struct onefile))) == NULL) + { + fatal("files.c, fill_list(): structure onefile malloc failed"); + } + + /* alloc filename memory and copy name into it */ + + if ((new_entry->fname = (char *) malloc(strlen(dp->d_name) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc filename string memory failed"); + } + + strcpy(new_entry->fname, dp->d_name); + + /* fill in remaining fields from filename */ + + tmp[0] = dp->d_name[4]; /* day msb */ + tmp[1] = dp->d_name[5]; /* day lsb */ + tmp[2] = '.'; + tmp[3] = dp->d_name[2]; /* month msb */ + tmp[4] = dp->d_name[3]; /* month lsb */ + tmp[5] = '.'; + tmp[6] = dp->d_name[0]; /* year msb */ + tmp[7] = dp->d_name[1]; /* year lsb */ + tmp[8] = '\0'; + + if((new_entry->date = (char *) malloc(strlen(tmp) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc date string memory failed"); + } + + strcpy(new_entry->date, tmp); + + tmp[0] = dp->d_name[6]; /* hour msb */ + tmp[1] = dp->d_name[7]; /* hour lsb */ + tmp[2] = ':'; + tmp[3] = dp->d_name[8]; /* minute msb */ + tmp[4] = dp->d_name[9]; /* minute lsb */ + tmp[5] = ':'; + tmp[6] = dp->d_name[10]; /* second msb */ + tmp[7] = dp->d_name[11]; /* second lsb */ + tmp[8] = '\0'; + + if((new_entry->time = (char *) malloc(strlen(tmp) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc time string memory failed"); + } + + strcpy(new_entry->time, tmp); + + /* destination number */ + + s = &dp->d_name[13]; + d = &tmp[0]; + + while(*s && (*s != '-')) + *d++ = *s++; + + *d = '\0'; + + if((new_entry->dstnumber = (char *) malloc(strlen(tmp) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc dstnumber string memory failed"); + } + + strcpy(new_entry->dstnumber, tmp); + + /* source number */ + + s++; + d = &tmp[0]; + + while(*s && (*s != '-')) + *d++ = *s++; + + *d = '\0'; + + if((new_entry->srcnumber = (char *) malloc(strlen(tmp) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc srcnumber string memory failed"); + } + + strcpy(new_entry->srcnumber, tmp); + + /* length in seconds */ + + s++; + d = &tmp[0]; + + while(*s && (*s != '-')) + *d++ = *s++; + + *d = '\0'; + + if((new_entry->seconds = (char *) malloc(strlen(tmp) + 1)) == NULL) + { + fatal("files.c, fill_list(): malloc seconds string memory failed"); + } + + strcpy(new_entry->seconds, tmp); + + /* search for alias and add if found */ + + new_entry->alias = get_alias(new_entry->srcnumber); + + /* sort entry into linked list */ + + first = store(new_entry, first); + + flcnt++; /* increment file count */ + } + closedir(dirp); /* close current dir */ + return(flcnt); /* ok return */ +} + +/*---------------------------------------------------------------------------* + * free the current malloc'ed list + *---------------------------------------------------------------------------*/ +void +free_list(void) +{ + register struct onefile *dir; + register struct onefile *tmp; + + dir = first; /* start of linked list */ + + while (dir) /* free all */ + { + tmp = dir->next; /* save ptr to next entry */ + free(dir->fname); /* free filename space */ + free(dir->date); + free(dir->time); + free(dir->srcnumber); + free(dir->dstnumber); + free(dir->seconds); + free(dir); /* free struct space */ + dir = tmp; /* ptr = ptr to next entry */ + } + first = NULL; /* first ptr = NULL */ + last = NULL; /* last ptr = NULL */ +} + +/*---------------------------------------------------------------------------* + * delete a file + *---------------------------------------------------------------------------*/ +void +delete(struct onefile *this) +{ + char buffer[MAXPATHLEN+1]; + + if(this == NULL) + return; + + sprintf(buffer, "%s", this->fname); + + unlink(buffer); + + free_list(); + + wclear(main_w); + + init_files(cur_pos); +} + +/*---------------------------------------------------------------------------* + * reread the spool directory + *---------------------------------------------------------------------------*/ +void +reread(void) +{ + free_list(); + + wclear(main_w); + + init_files(cur_pos); +} + +/*---------------------------------------------------------------------------* + * play a file + *---------------------------------------------------------------------------*/ +void +play(struct onefile *this) +{ + char buffer[MAXPATHLEN+1]; + + if(this == NULL) + return; + + sprintf(buffer, playstring, this->fname); + + system(buffer); +} + +/*---------------------------------- EOF -------------------------------------*/ diff --git a/usr.sbin/i4b/isdntel/isdntel.8 b/usr.sbin/i4b/isdntel/isdntel.8 new file mode 100644 index 0000000..d87c848 --- /dev/null +++ b/usr.sbin/i4b/isdntel/isdntel.8 @@ -0,0 +1,94 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" last edit-date: [Sat Dec 5 18:16:19 1998] +.\" +.\" $Id: isdntel.8,v 1.6 1998/12/05 18:03:58 hm Exp $ +.\" +.Dd July 11, 1998 +.Dt isdntel 8 +.Sh NAME +.Nm isdntel +.Nd isdn4bsd telephone answering management utility +.Sh SYNOPSIS +.Nm isdntel +.Op Fl a Ar aliasfile +.Op Fl d Ar spooldir +.Op Fl p Ar playcommand +.Op Fl t Ar timeout +.Sh DESCRIPTION +.Nm +is used to provide an "answering machine" functionality for incoming +telephone voice messages. +.Pp +The following options are supported: +.Bl -tag -width Ds +.It Fl a +Use +.Ar aliasfile +as the pathname for an aliasfile containing aliases for phone numbers. The +default path is +.Em /etc/isdn/isdntel.alias . +The format of an alias entry is the number string followed by one or more +spaces or tabs. The rest of the line is taken as the alias string. Comments +are introduced by a leading blank, tab or "#" character. +.It Fl d +Use +.Ar spooldir +as the directory where the incoming voice messages are stored by the +"answ" script called by +.Xr isdnd 8 . +This defaults to the directory +.Em /var/isdn . +The format of a voice message filename is: +.Pp +.Dl YYMMDDhhmmss-dest_number-source_number-length_in_secs +.It Fl p +Use +.Ar playcommand +as the command string to execute for playing a voice message to some audio +output facility. The characters +.Em %s +are replaced by the currently selected filename. The default string is +.Em cat %s | alaw2ulaw >/dev/audio +.It Fl t +The value for +.Ar timeout +specifies the time in seconds the program rereads the spool directory +when there is no keyboard activity. +.El +.Pp +The screen output should be obvious. If in doubt, consult the source. +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnd.rc 5 +.Xr i4btel 4 + +.Sh BUGS +Still two or more left. + +.Sh AUTHOR +The +.Nm +utility and this manual page were written by Hellmuth Michaelis (hm@kts.org) diff --git a/usr.sbin/i4b/isdntel/main.c b/usr.sbin/i4b/isdntel/main.c new file mode 100644 index 0000000..fd6a3b2 --- /dev/null +++ b/usr.sbin/i4b/isdntel/main.c @@ -0,0 +1,395 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntel - isdn4bsd telephone answering machine support + * ====================================================== + * + * $Id: main.c,v 1.6 1998/12/05 18:03:59 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:16:33 1998] + * + *----------------------------------------------------------------------------*/ + +#define MAIN +#include "defs.h" +#include "alias.h" + +static void usage( void ); + +static int top_dis = 0; +static int bot_dis = 0; +static int cur_pos_scr = 0; + +static void makecurrent(int cur_pos, struct onefile *cur_file, int cold); + +/*---------------------------------------------------------------------------* + * program entry + *---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int i; + int kchar; + + char *spooldir = SPOOLDIR; + char *playstring = PLAYCMD; + char *aliasfile = ALIASFILE; + int rrtimeout = REREADTIMEOUT; + + extern char *optarg; + + while ((i = getopt(argc, argv, "a:d:p:t:?")) != EOF) + { + switch (i) + { + case 'a': + aliasfile = optarg; + break; + + case 'd': + spooldir = optarg; + break; + + case 'p': + playstring = optarg; + break; + + case 't': + if(isdigit(*optarg)) + { + rrtimeout = strtoul(optarg, NULL, 10); + } + else + { + usage(); + } + break; + + case '?': + default: + usage(); + break; + } + } + + if(rrtimeout < 10) + rrtimeout = 10; + + if((chdir(spooldir)) != 0) + fatal("cannot change directory to spooldir %s!", spooldir); + + init_alias(aliasfile); + + init_screen(); + + init_files(0); + + /* go into loop */ + + for (;;) + { + fd_set set; + struct timeval timeout; + + FD_ZERO(&set); + FD_SET(STDIN_FILENO, &set); + timeout.tv_sec = rrtimeout; + timeout.tv_usec = 0; + + /* if no char is available within timeout, reread spool */ + + if((select(STDIN_FILENO + 1, &set, NULL, NULL, &timeout)) <= 0) + { + reread(); + continue; + } + + kchar = wgetch(main_w); /* get char */ + + switch (kchar) + { + case CR: + case LF: +#ifdef KEY_ENTER + case KEY_ENTER: +#endif + do_menu(); + break; + + case KEY_UP: /* up-move cursor */ + if(cur_file && cur_file->prev) + { + cur_file = cur_file->prev; + cur_pos--; + } + break; + + + case TAB: + case KEY_DOWN: /* down-move cursor */ + if(cur_file && cur_file->next) + { + cur_file = cur_file->next; + cur_pos++; + } + break; + + case KEY_HOME: /* move cursor to first dir */ + break; + + case KEY_LL: /* move cursor to last file */ + break; + + case CNTRL_D: + do_quit(0); + break; + + case CNTRL_L: /* refresh */ + touchwin(curscr); + wrefresh(curscr); + break; + + } + makecurrent(cur_pos, cur_file, 0); + } + + do_quit(0); + + return(0); +} + +/*---------------------------------------------------------------------------* + * handle horizontal selection bar movement + *---------------------------------------------------------------------------*/ +static void +makecurrent(int cur_pos, struct onefile *cur_file, int cold) +{ + static int lastpos; + static struct onefile *lastfile; + char buffer[256]; + + /* un-higlight current horizontal bar */ + + if(!cold && lastfile && cur_file) + { + sprintf(buffer, "%s %s %-16s %-16s %-20s %-6s%*s", + lastfile->date, lastfile->time, + lastfile->dstnumber, lastfile->srcnumber, + lastfile->alias == NULL ? "-/-" : lastfile->alias, + lastfile->seconds, + COLS - LAST_POS - 2, ""); + + wattroff(main_w, A_REVERSE); + mvwprintw(main_w, lastpos, 0, "%s", buffer); + wattroff(main_w, A_REVERSE); + } + + if(cur_file == NULL) + { + lastpos = cur_pos_scr; + lastfile = cur_file; + return; + } + + /* have to scroll up or down ? */ + + if(cur_pos >= bot_dis) + { + /* scroll up */ + + wscrl(main_w, 1); + + bot_dis++; + top_dis++; + cur_pos_scr = LINES-START_O-3; + } + else if(cur_pos < top_dis) + { + /* scroll down */ + + wscrl(main_w, -1); + + bot_dis--; + top_dis--; + cur_pos_scr = 0; + } + else + { + cur_pos_scr = cur_pos - top_dis; + } + + sprintf(buffer, "%s %s %-16s %-16s %-20s %-6s%*s", + cur_file->date, cur_file->time, + cur_file->dstnumber, cur_file->srcnumber, + cur_file->alias == NULL ? "-/-" : cur_file->alias, + cur_file->seconds, + COLS - LAST_POS - 2, ""); + + wattron(main_w, A_REVERSE); + mvwprintw(main_w, cur_pos_scr, 0, "%s", buffer); + wattroff(main_w, A_REVERSE); + + lastpos = cur_pos_scr; + lastfile = cur_file; + + wrefresh(main_w); +} + +/*---------------------------------------------------------------------------* + * exit program + *---------------------------------------------------------------------------*/ +void +do_quit(int exitval) +{ + move(LINES-1, 0); + clrtoeol(); + refresh(); + endwin(); + exit(exitval); +} + +/*---------------------------------------------------------------------------* + * usage display and exit + *---------------------------------------------------------------------------*/ +static void +usage(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, "isdntel - isdn telephone answering management support utility (version %s.%s)\n", VERSION, REL); + fprintf(stderr, " usage: isdntel -a <filename> -d <directory> -p <command> -t <timeout>\n"); + fprintf(stderr, " -a <filename> use filename as alias file\n"); + fprintf(stderr, " -d <directory> use directory as spool directory\n"); + fprintf(stderr, " -p <command> specify commandline for play command\n"); + fprintf(stderr, " -t <timeout> spool directory reread timeout in seconds\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/*---------------------------------------------------------------------------* + * fatal error exit + *---------------------------------------------------------------------------*/ +void +fatal(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + if(curses_ready) + { + move(LINES-1, 0); + clrtoeol(); + refresh(); + endwin(); + } + + fprintf(stderr, "\nFatal error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n\n"); + + va_end(ap); + + exit(1); +} + +/*---------------------------------------------------------------------------* + * error printing + *---------------------------------------------------------------------------*/ +void +error(char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + + if(curses_ready) + { + wprintw(main_w, "ERROR: "); + vwprintw(main_w, fmt, ap); + wprintw(main_w, "\n"); + wrefresh(main_w); + } + else + { + fprintf(stderr, "ERROR: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + } + + va_end(ap); +} + +/*---------------------------------------------------------------------------* + * read files and fill display + *---------------------------------------------------------------------------*/ +void +init_files(int inipos) +{ + int i; + + nofiles = fill_list(); + + top_dis = 0; + bot_dis = 0; + + cur_file = first; + + cur_pos = 0; + cur_pos_scr = 0; + + if(nofiles == 0) + return; + + for(i=0; (i < nofiles) && (i < (LINES-START_O-2)); i++) + { + mvwprintw(main_w, i, 0, "%s %s", cur_file->date, cur_file->time); + mvwprintw(main_w, i, DST_POS, "%s", cur_file->dstnumber); + mvwprintw(main_w, i, SRC_POS, "%s", cur_file->srcnumber); + mvwprintw(main_w, i, ALI_POS,"%s", cur_file->alias == NULL ? "-/-" : cur_file->alias); + mvwprintw(main_w, i, SEC_POS,"%s", cur_file->seconds); + + bot_dis++; + + if((cur_file = cur_file->next) == NULL) + break; + } + + cur_file = first; + + if(inipos) + { + for(i=0; i < inipos; i++) + { + if(cur_file->next != NULL) + cur_file = cur_file->next; + else + break; + } + } + makecurrent(cur_pos, cur_file, 1); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntelctl/Makefile b/usr.sbin/i4b/isdntelctl/Makefile new file mode 100644 index 0000000..b38f206 --- /dev/null +++ b/usr.sbin/i4b/isdntelctl/Makefile @@ -0,0 +1,5 @@ +PROG = isdntelctl +SRCS = main.c +MAN8 = isdntelctl.8 + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/isdntelctl/isdntelctl.8 b/usr.sbin/i4b/isdntelctl/isdntelctl.8 new file mode 100644 index 0000000..2bd45d2 --- /dev/null +++ b/usr.sbin/i4b/isdntelctl/isdntelctl.8 @@ -0,0 +1,78 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdntelctl.8,v 1.4 1998/12/14 10:31:55 hm Exp $ +.\" +.\" last edit-date: [Mon Dec 14 11:34:51 1998] +.\" +.Dd December 14, 1998 +.Dt isdntelctl 8 +.Sh NAME +.Nm isdntelctl +.Nd control isdn4bsd telephone sound format conversion +.Sh SYNOPSIS +.Nm +.Op Fl c +.Op Fl g +.Op Fl u Ar unit +.Op Fl A +.Op Fl U +.Sh DESCRIPTION +.Nm isdntelctl +is part of the isdn4bsd package and is used to configure the sound format +conversion facilities of the /dev/i4btel interfaces. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl c +Clear the telephone input queue. +.It Fl g +Get the sound format currently in use. +.It Fl u +Set the /dev/i4btel unit number. The default value is zero to access +device /dev/i4btel0. +.It Fl A +Set sound format to A-Law. +.It Fl U +Set sound format to u-Law. +.Pp +.Sh FILES +/dev/i4btel<n> + +.Sh STANDARDS +A-Law and u-Law are specified in ITU Recommendation G.711. + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +isdntelctl -g +.Ed +.Pp +displays the currently used sound format for device /dev/i4btel0. + +.Sh AUTHOR +The +.Nm +utility and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/isdntelctl/main.c b/usr.sbin/i4b/isdntelctl/main.c new file mode 100644 index 0000000..4309b24 --- /dev/null +++ b/usr.sbin/i4b/isdntelctl/main.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * isdntelctl - i4b set telephone interface options + * ------------------------------------------------ + * + * $Id: main.c,v 1.4 1998/12/14 10:31:57 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:17:17 1998] + * + *---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> + +#include <machine/i4b_tel_ioctl.h> + +static void usage ( void ); + +#define I4BTELDEVICE "/dev/i4btel" + +int opt_get = 0; +int opt_unit = 0; +int opt_U = 0; +int opt_A = 0; +int opt_C = 0; + +/*---------------------------------------------------------------------------* + * program entry + *---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int c; + int ret; + int telfd; + char namebuffer[128]; + + while ((c = getopt(argc, argv, "cgu:AU?")) != EOF) + { + switch(c) + { + case 'c': + opt_C = 1; + break; + + case 'g': + opt_get = 1; + break; + + case 'u': + opt_unit = atoi(optarg); + if(opt_unit < 0 || opt_unit > 9) + usage(); + break; + + case 'A': + opt_A = 1; + break; + + case 'U': + opt_U = 1; + break; + + case '?': + default: + usage(); + break; + } + } + + if(opt_get == 0 && opt_U == 0 && opt_A && opt_C == 0) + { + opt_get = 1; + } + + if((opt_get + opt_U + opt_A + opt_C) > 1) + { + usage(); + } + + sprintf(namebuffer,"%s%d", I4BTELDEVICE, opt_unit); + + if((telfd = open(namebuffer, O_RDWR)) < 0) + { + fprintf(stderr, "isdntelctl: cannot open %s: %s\n", namebuffer, strerror(errno)); + exit(1); + } + + if(opt_get) + { + int format; + + if((ret = ioctl(telfd, I4B_TEL_GETAUDIOFMT, &format)) < 0) + { + fprintf(stderr, "ioctl I4B_TEL_GETAUDIOFMT failed: %s", strerror(errno)); + exit(1); + } + + if(format == CVT_NONE) + { + printf("device %s uses A-Law sound format\n", namebuffer); + } + else if(format == CVT_ALAW2ULAW) + { + printf("device %s uses u-Law sound format\n", namebuffer); + } + else + { + printf("ERROR, device %s uses unknown format %d!\n", namebuffer, format); + } + exit(0); + } + + if(opt_A) + { + int format = CVT_NONE; + + if((ret = ioctl(telfd, I4B_TEL_SETAUDIOFMT, &format)) < 0) + { + fprintf(stderr, "ioctl I4B_TEL_SETAUDIOFMT failed: %s", strerror(errno)); + exit(1); + } + exit(0); + } + + if(opt_U) + { + int format = CVT_ALAW2ULAW; + + if((ret = ioctl(telfd, I4B_TEL_SETAUDIOFMT, &format)) < 0) + { + fprintf(stderr, "ioctl I4B_TEL_SETAUDIOFMT failed: %s", strerror(errno)); + exit(1); + } + exit(0); + } + if(opt_C) + { + int dummy; + if((ret = ioctl(telfd, I4B_TEL_EMPTYINPUTQUEUE, &dummy)) < 0) + { + fprintf(stderr, "ioctl I4B_TEL_EMPTYINPUTQUEUE failed: %s", strerror(errno)); + exit(1); + } + exit(0); + } + return(0); +} + +/*---------------------------------------------------------------------------* + * usage display and exit + *---------------------------------------------------------------------------*/ +static void +usage(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, "isdntelctl - i4b telephone i/f control, compiled %s %s\n",__DATE__, __TIME__); + fprintf(stderr, "usage: isdndebug -e -h -g -l <layer> -m -r -s <value> -u <unit> -z -H\n"); + fprintf(stderr, " -g get current settings\n"); + fprintf(stderr, " -u unit specify unit number\n"); + fprintf(stderr, " -A set interface to A-Law coding\n"); + fprintf(stderr, " -U set interface to u-Law coding\n"); + fprintf(stderr, " -c clear input queue\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntest/Makefile b/usr.sbin/i4b/isdntest/Makefile new file mode 100644 index 0000000..c1240cc --- /dev/null +++ b/usr.sbin/i4b/isdntest/Makefile @@ -0,0 +1,8 @@ +PROG = isdntest +SRCS = main.c +MAN8 = isdntest.8 + +install: + @echo isdntest is not installed automatically + +.include <bsd.prog.mk> diff --git a/usr.sbin/i4b/isdntest/isdntest.8 b/usr.sbin/i4b/isdntest/isdntest.8 new file mode 100644 index 0000000..7e03523 --- /dev/null +++ b/usr.sbin/i4b/isdntest/isdntest.8 @@ -0,0 +1,103 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdntest.8,v 1.6 1998/12/16 13:39:47 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:17:35 1998] +.\" +.Dd July 9, 1998 +.Dt isdntest 8 +.Sh NAME +.Nm isdntest +.Nd isdn4bsd debugging and verification tool +.Sh SYNOPSIS +.Nm +.Op Fl c Ar unit +.Op Fl h +.Op Fl i Ar number +.Op Fl o Ar number +.Op Fl w +.Sh DESCRIPTION +.Nm isdntest +is part of the isdn4bsd package and may be used as a stimulation tool +for debugging the isdn4bsd kernel functionality. +.Pp +NOTE: +.Nm Isdntest +must be run +.Em instead +of the +.Xr isdnd 8 +daemon and can not be used while the daemon runs. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl c +Use controller unit number for test. +.It Fl h +Use HDLC as the B channel layer 1 protocol instead of no protocol. +.It Fl i +Use number to verify the incoming number. +.It Fl o +Use number as the outgoing number to dial. +.It Fl w +Wait for keyboard input for terminating the call. +.El +.Pp +The +.Nm +utility is currently of not much use for end users, it is primarily a debugging +tool for development and is part of the release in the hope, that someone +enhances it as a real self test and setup-verification tool! +.Pp +.Nm Isdntest +does almost no error checking and error recovery, so unexpected +hangs or crashes may occur. + +.Sh EXAMPLES +For the following example, it is assumed that a machine with isdn4bsd +installed is connected to an S0 bus and that one of the valid MSN's (MSN = Multiple Subscriber Number += telephone number) on this bus is +.Em 42 . +The +.Xr isdnd 8 +.Em must +not currently running on that machine! Executing: +.Bd -literal -offset indent +isdntest -i 42 -o 42 +.Ed +.Pp +will setup an outgoing call from that machine to itself, connect to itself +and disconnect after 5 seconds. +.Nm Isdntest +has to be finished by the user by entering Control-C. +.Pp +.Sh FILES +/dev/i4b + +.Sh AUTHOR +The +.Nm +utility and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/isdntest/main.c b/usr.sbin/i4b/isdntest/main.c new file mode 100644 index 0000000..8e75be2 --- /dev/null +++ b/usr.sbin/i4b/isdntest/main.c @@ -0,0 +1,738 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * main.c - i4b selftest utility + * ----------------------------- + * + * $Id: main.c,v 1.9 1998/12/05 18:04:06 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:18:17 1998] + * + *---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <signal.h> +#include <errno.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <ctype.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_cause.h> + +static void kbdrdhdl ( void ); +static void isdnrdhdl (int isdnfd ); + +void handle_connect_ind(unsigned char *ptr); +void handle_disconnect(unsigned char *ptr); +void handle_connect_active_ind(unsigned char *ptr); + +int connect_response(int isdnfd, unsigned int cdid, int response); +int disconnect_request(int isdnfd, unsigned int cdid); +unsigned int get_cdid(int isdnfd); +int connect_request(int isdnfd, unsigned int cdid); +int do_test(void); +static void cleanup(void); +static void usage(void); +void setup_wrfix(int len, unsigned char *buf); +int check_rd(int len, unsigned char *wbuf, unsigned char *rdbuf); + +static int isdnfd; +char outgoingnumber[32]; +char incomingnumber[32]; +int debug_level = 0; + +#define I4BDEVICE "/dev/i4b" +#define DATADEV0 "/dev/i4brbch0" +#define DATAUNIT0 0 +#define DATADEV1 "/dev/i4brbch1" +#define DATAUNIT1 1 + +unsigned int out_cdid = CDID_UNUSED; +unsigned int in_cdid = CDID_UNUSED; + +int waitchar = 0; +int usehdlc = 0; +int controller = 0; +int dotest = 0; + +/*---------------------------------------------------------------------------* + * program entry + *---------------------------------------------------------------------------*/ +int +main(int argc, char **argv) +{ + int i; + int c; + fd_set set; + int ret; + char *ptr; + + incomingnumber[0] = '\0'; + outgoingnumber[0] = '\0'; + + while ((c = getopt(argc, argv, "c:d:hi:o:t:w?")) != EOF) + { + switch(c) + { + case 'c': + if(isdigit(*optarg)) + { + controller = strtoul(optarg, NULL, 10); + } + else + { + fprintf(stderr, "Error: option -c requires a numeric argument!\n"); + usage(); + } + break; + + case 'd': + if(isdigit(*optarg)) + { + debug_level = strtoul(optarg, NULL, 10); + } + else + { + fprintf(stderr, "Error: option -d requires a numeric argument!\n"); + usage(); + } + break; + + case 'o': + i = 0; + ptr = optarg; + + while(*ptr) + { + if(isdigit(*ptr)) + { + outgoingnumber[i++] = *ptr++; + } + else + { + fprintf(stderr, "Error: option -o requires a numeric argument!\n"); + usage(); + } + } + outgoingnumber[i] = '\0'; + break; + + case 'i': + i = 0; + ptr = optarg; + + while(*ptr) + { + if(isdigit(*ptr)) + { + incomingnumber[i++] = *ptr++; + } + else + { + fprintf(stderr, "Error: option -i requires a numeric argument!\n"); + usage(); + } + } + incomingnumber[i] = '\0'; + break; + + case 'w': + waitchar = 1; + break; + + case 'h': + usehdlc = 1; + break; + + case 't': + if(isdigit(*optarg)) + { + dotest = strtoul(optarg, NULL, 10); + } + else + { + fprintf(stderr, "Error: option -t requires a numeric argument!\n"); + usage(); + } + break; + + case '?': + default: + usage(); + break; + } + } + + if((strlen(incomingnumber) == 0) || (strlen(outgoingnumber) == 0)) + usage(); + + fprintf(stderr, "isdntest: accepting calls from telephone number [%s] \n", incomingnumber); + fprintf(stderr, "isdntest: calling out telephone number [%s] \n", outgoingnumber); + + if((atexit(cleanup)) != 0) + { + fprintf(stderr, "isdntest: atexit error: %s\n", strerror(errno)); + exit(1); + } + + /* open isdn device */ + + if((isdnfd = open(I4BDEVICE, O_RDWR)) < 0) + { + fprintf(stderr, "\nisdntest: cannot open %s: %s\n", I4BDEVICE, strerror(errno)); + fprintf(stderr, " isdnd is probably running, to use isdntest,\n"); + fprintf(stderr, " terminate isdnd and then run isdntest again!\n"); + exit(1); + } + + if((out_cdid = get_cdid(isdnfd)) == 0) + { + fprintf(stderr, "isdntest: error getting cdid: %s\n", strerror(errno)); + exit(1); + } + + if((connect_request(isdnfd, out_cdid)) == -1) + { + fprintf(stderr, "isdntest: error, outgoing call failed!\n"); + exit(1); + } + + for(;;) + { + FD_ZERO(&set); + + FD_SET(0, &set); + + FD_SET(isdnfd, &set); + + ret = select(isdnfd + 1, &set, NULL, NULL, NULL); + + if(ret > 0) + { + if(FD_ISSET(isdnfd, &set)) + isdnrdhdl(isdnfd); + + if(FD_ISSET(0, &set)) + kbdrdhdl(); + } + else + { + fprintf(stderr, "isdntest: select error: %s\n", strerror(errno)); + } + } +} + +/*---------------------------------------------------------------------------* + * data from keyboard available + *---------------------------------------------------------------------------*/ +static void +kbdrdhdl(void) +{ + cleanup(); + exit(2); +} + +/*---------------------------------------------------------------------------* + * data from /dev/isdn available, read and process them + *---------------------------------------------------------------------------*/ +static void +isdnrdhdl(int isdnfd) +{ + static unsigned char buf[1024]; + int len; + + if((len = read(isdnfd, buf, 1024 - 1)) > 0) + { + switch (buf[0]) + { + case MSG_CONNECT_IND: + handle_connect_ind(&buf[0]); + break; + + case MSG_CONNECT_ACTIVE_IND: + handle_connect_active_ind(&buf[0]); + break; + + case MSG_DISCONNECT_IND: + handle_disconnect(&buf[0]); + break; + + default: + if(debug_level) + fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]); + break; + } + } + else + { + fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len); + } +} + +/*---------------------------------------------------------------------------* + * usage display and exit + *---------------------------------------------------------------------------*/ +static void +usage(void) +{ + fprintf(stderr, "\n"); + fprintf(stderr, "isdntest - i4b selftest, compiled %s %s\n",__DATE__, __TIME__); + fprintf(stderr, "usage: isdntest -c <ctrl> -h -i <telno> -o <telno>\n"); + fprintf(stderr, " -c <ctrl> specify controller to use\n"); + fprintf(stderr, " -h use HDLC as Bchannel protocol\n"); + fprintf(stderr, " -i <telno> incoming telephone number\n"); + fprintf(stderr, " -o <telno> outgoing telephone number\n"); + fprintf(stderr, " -w wait for keyboard entry to disconnect\n"); + fprintf(stderr, " -t num send test pattern num times\n"); + fprintf(stderr, "\n"); + exit(1); +} + +/*---------------------------------------------------------------------------* + * initiate an outgoing connection + *---------------------------------------------------------------------------*/ +int +connect_request(int isdnfd, unsigned int cdid) +{ + msg_connect_req_t mcr; + int ret; + + bzero(&mcr, sizeof(msg_connect_req_t)); + + mcr.controller = controller; + mcr.channel = CHAN_ANY; /* any channel */ + mcr.cdid = cdid; /* cdid from get_cdid() */ + + if(usehdlc) + mcr.bprot = BPROT_RHDLC;/* b channel protocol */ + else + mcr.bprot = BPROT_NONE; /* b channel protocol */ + + mcr.driver = BDRV_RBCH; /* raw b channel driver */ + mcr.driver_unit = DATAUNIT0; /* raw b channel driver unit */ + + strcpy(mcr.dst_telno, outgoingnumber); + strcpy(mcr.src_telno, incomingnumber); + + if((ret = ioctl(isdnfd, I4B_CONNECT_REQ, &mcr)) < 0) + { + fprintf(stderr, "ioctl I4B_CONNECT_REQ failed: %s", strerror(errno)); + return(-1); + } + fprintf(stderr, "isdntest: calling out to telephone number [%s] \n", outgoingnumber); + return(0); +} + +/*---------------------------------------------------------------------------* + * handle setup indicator + *---------------------------------------------------------------------------*/ +void +handle_connect_ind(unsigned char *ptr) +{ + msg_connect_ind_t *msi = (msg_connect_ind_t *)ptr; + + fprintf(stderr, "isdntest: incoming SETUP: from %s to %s\n", + msi->src_telno, + msi->dst_telno); + + fprintf(stderr, " channel %d, controller %d, bprot %d, cdid %d\n", + msi->channel, + msi->controller, + msi->bprot, + msi->header.cdid); + + in_cdid = msi->header.cdid; + + if(strcmp(msi->dst_telno, outgoingnumber)) + { + msg_connect_resp_t msr; + int ret; + + fprintf(stderr, "isdntest: ignoring incoming SETUP: my number [%s] != outgoing [%s]\n", + msi->dst_telno, outgoingnumber); + + msr.cdid = in_cdid; + msr.response = SETUP_RESP_DNTCRE; + + if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0) + { + fprintf(stderr, "ioctl I4B_CONNECT_RESP ignore failed: %s", strerror(errno)); + exit(1); + } + + } + else + { + msg_connect_resp_t msr; + int ret; + + fprintf(stderr, "isdntest: accepting call, sending CONNECT_RESPONSE .....\n"); + + msr.cdid = in_cdid; + msr.response = SETUP_RESP_ACCEPT; + + if(usehdlc) + msr.bprot = BPROT_RHDLC; + else + msr.bprot = BPROT_NONE; + + msr.driver = BDRV_RBCH; + msr.driver_unit = DATAUNIT1; + + if((ret = ioctl(isdnfd, I4B_CONNECT_RESP, &msr)) < 0) + { + fprintf(stderr, "ioctl I4B_CONNECT_RESP accept failed: %s", strerror(errno)); + exit(1); + } + } +} + +#define SLEEPTIME 5 + +/*---------------------------------------------------------------------------* + * handle connection active + *---------------------------------------------------------------------------*/ +void +handle_connect_active_ind(unsigned char *ptr) +{ + msg_connect_active_ind_t *msi = (msg_connect_active_ind_t *)ptr; + int i; + + fprintf(stderr, "isdntest: connection active, cdid %d\n", msi->header.cdid); + + if(out_cdid == msi->header.cdid) + { + if(waitchar) + { + fprintf(stderr, "isdntest: press any key to disconnect ...%c%c%c\n", 0x07, 0x07, 0x07); + getchar(); + } + else + { + if(dotest) + { + do_test(); + } + else + { + fprintf(stderr, "isdntest: %d secs delay until disconnect:", SLEEPTIME); + + for(i=0; i < SLEEPTIME;i++) + { + fprintf(stderr, " ."); + sleep(1); + } + fprintf(stderr, "\n"); + } + cleanup(); + } + } +} + +/*---------------------------------------------------------------------------* + * handle disconnect indication + *---------------------------------------------------------------------------*/ +void +handle_disconnect(unsigned char *ptr) +{ + msg_disconnect_ind_t *mdi = (msg_disconnect_ind_t *)ptr; + + if(mdi->header.cdid == out_cdid) + { + fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (out_cdid), cause %d\n", + mdi->header.cdid, mdi->cause); + + out_cdid = CDID_UNUSED; + } + else if(mdi->header.cdid == in_cdid) + { + fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (in_cdid), cause %d\n", + mdi->header.cdid, mdi->cause); + in_cdid = CDID_UNUSED; + } + else + { + fprintf(stderr, "isdntest: incoming disconnect indication, cdid %d (???), cause %d\n", + mdi->header.cdid, mdi->cause); + } +} + +/*---------------------------------------------------------------------------* + * hang up + *---------------------------------------------------------------------------*/ +int +disconnect_request(int isdnfd, unsigned int cdid) +{ + msg_discon_req_t mdr; + int ret; + + mdr.cdid = cdid; + mdr.cause = (CAUSET_I4B << 8) | CAUSE_I4B_NORMAL; + + if((ret = ioctl(isdnfd, I4B_DISCONNECT_REQ, &mdr)) < 0) + { + fprintf(stderr, "ioctl I4B_DISCONNECT_REQ failed: %s", strerror(errno)); + return(-1); + } + fprintf(stderr, "isdntest: sending disconnect request\n"); + return(0); +} + +/*---------------------------------------------------------------------------* + * get cdid from kernel + *---------------------------------------------------------------------------*/ +unsigned int +get_cdid(int isdnfd) +{ + msg_cdid_req_t mcr; + int ret; + + mcr.cdid = 0; + + if((ret = ioctl(isdnfd, I4B_CDID_REQ, &mcr)) < 0) + { + fprintf(stderr, "ioctl I4B_CDID_REQ failed: %s", strerror(errno)); + return(0); + } + fprintf(stderr, "isdntest: got cdid %d from kernel\n", mcr.cdid); + return(mcr.cdid); +} + +/*---------------------------------------------------------------------------* + * make shure all cdid's are inactive before leaving + *---------------------------------------------------------------------------*/ +void cleanup(void) +{ + int len; + char buf[1024]; + + if(out_cdid != CDID_UNUSED) + { + fprintf(stderr, "isdntest: cleanup, send disconnect req for out_cdid %d, in_cdid %d\n", out_cdid, in_cdid); + disconnect_request(isdnfd, out_cdid); + } + + while((out_cdid != CDID_UNUSED) || (in_cdid != CDID_UNUSED)) + { + fprintf(stderr, "isdntest: cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid); + + if((len = read(isdnfd, buf, 1024 - 1)) > 0) + { + switch (buf[0]) + { + case MSG_CONNECT_IND: + handle_connect_ind(&buf[0]); + break; + + case MSG_CONNECT_ACTIVE_IND: + handle_connect_active_ind(&buf[0]); + break; + + case MSG_DISCONNECT_IND: + handle_disconnect(&buf[0]); + break; + + default: + fprintf(stderr, "isdntest: unknown message 0x%x = %c\n", buf[0], buf[0]); + break; + } + } + else + { + fprintf(stderr, "isdntest: read error, errno = %d, length = %d", errno, len); + } + } + fprintf(stderr, "isdntest: exit cleanup, out_cdid %d, in_cdid %d\n", out_cdid, in_cdid); +} + +/*---------------------------------------------------------------------------* + * test the b-channels + *---------------------------------------------------------------------------*/ +int do_test(void) +{ + +#define FPH 0x3c +#define FPL 0x66 + + int fd0, fd1; + unsigned char wrbuf[2048]; + unsigned char rdbuf[2048]; + int sz; + fd_set set; + struct timeval timeout; + int ret; + int frame; + int errcnt; + int frm_len; + int bytecnt = 0; + time_t start_time; + time_t cur_time; + time_t run_time; + + if((fd0 = open(DATADEV0, O_RDWR)) == -1) + { + fprintf(stderr, "open of %s failed: %s", DATADEV0, strerror(errno)); + return(-1); + } + + if((fd1 = open(DATADEV1, O_RDWR)) == -1) + { + fprintf(stderr, "open of %s failed: %s", DATADEV1, strerror(errno)); + return(-1); + } + + printf("\n"); + frame = 0; + errcnt = 0; + + frm_len = 2; + + start_time = time(NULL); + + printf(" frame size errors totalbytes bps elapsedtime\n"); + + for(;dotest > 0; dotest--) + { + setup_wrfix(frm_len, &wrbuf[0]); + + frame++; + + bytecnt += frm_len; + + printf("%6d %4d", frame, frm_len); + fflush(stdout); + + if((sz = write(fd0, wrbuf, frm_len)) != frm_len) + { + fprintf(stderr, "write (%d of %d bytes) to %s failed: %s\n", sz, frm_len, DATADEV0, strerror(errno)); + } + + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + FD_ZERO(&set); + + FD_SET(0, &set); + FD_SET(fd1, &set); + + ret = select(fd1+1, &set, NULL, NULL, &timeout); + + if(ret > 0) + { + if(FD_ISSET(fd1, &set)) + { + if((sz = read(fd1, rdbuf, 2048)) != frm_len) + { + fprintf(stderr, "read (%d bytes) from %s failed: %s\n", sz, DATADEV1, strerror(errno)); + } + + cur_time = time(NULL); + run_time = difftime(cur_time, start_time); + + if(run_time == 0) + run_time = 1; + + printf(" %6d %10d %4d %2.2d:%2.2d:%2.2d \r", + errcnt, bytecnt, + (int)((int)bytecnt/(int)run_time), + (int)run_time/3600, (int)run_time/60, (int)run_time%60); + fflush(stdout); + + errcnt += check_rd(frm_len, &wrbuf[0], &rdbuf[0]); + +#ifdef NOTDEF + for(i=0; i<sz; i++) + { + printf("0x%02x ", (unsigned char)rdbuf[i]); + } + printf("\n"); +#endif + } + + if(FD_ISSET(0, &set)) + { + return(0); + printf("\n\n"); + } + } + else + { + fprintf(stderr, "isdntest, do_test: select error: %s\n", strerror(errno)); + } + + frm_len = frm_len*2; + if(frm_len > 2048) + frm_len = 2; + + } + printf("\n\n"); + return(0); +} + +void +setup_wrfix(int len, unsigned char *buf) +{ + register int i; + + for(i=0; i<len;) + { + *buf = FPH; + buf++; + *buf = FPL; + buf++; + i+=2; + } +} + +int +check_rd(int len, unsigned char *wbuf, unsigned char *rbuf) +{ + register int i; + int ret = 0; + + for(i=0; i<len; i++) + { + if(*wbuf != *rbuf) + { + fprintf(stderr, "\nERROR, byte %d, written 0x%02x, read 0x%02x\n", i, *wbuf, *rbuf); + ret++; + } + wbuf++; + rbuf++; + } + return(ret); +} + + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/1tr6.c b/usr.sbin/i4b/isdntrace/1tr6.c new file mode 100644 index 0000000..1c8c184 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/1tr6.c @@ -0,0 +1,754 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * 1tr6.c - print 1TR6 protocol traces + * ----------------------------------- + * + * $Id: 1tr6.c,v 1.4 1998/12/05 18:04:08 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:18:38 1998] + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" + +static int p_1tr6address(char *pbuf, unsigned char buf[]); +static int p_1tr6cause(char *pbuf, unsigned char buf[]); + +/*---------------------------------------------------------------------------* + * decode the (german) national specific 1TR6 protocol + *---------------------------------------------------------------------------*/ +void +decode_1tr6(char *pbuf, int n, int off, unsigned char *buf, int raw) +{ + int codeset = 0; + int oldcodeset = 0; + int codelock = 0; + + int pd; + int len; + int j; + int i; + + if(n <= 0) + return; + + *pbuf = '\0'; + + if(raw) + { + for (i = 0; i < n; i += 16) + { + sprintf((pbuf+strlen(pbuf)),"Dump:%.3d ", i+off); + for (j = 0; j < 16; j++) + if (i + j < n) + sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf))," "); + sprintf((pbuf+strlen(pbuf))," "); + for (j = 0; j < 16 && i + j < n; j++) + if (isprint(buf[i + j])) + sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf)),"."); + sprintf((pbuf+strlen(pbuf)),"\n"); + } + } + + sprintf((pbuf+strlen(pbuf)), "1TR6: "); + + /* protocol discriminator */ + + i = 0; + + pd = buf[i]; + + switch(pd) + { + case 0x40: + sprintf((pbuf+strlen(pbuf)), "pd=N0, "); + break; + case 0x41: + sprintf((pbuf+strlen(pbuf)), "pd=N1, "); + break; + default: + sprintf((pbuf+strlen(pbuf)), "pd=UNDEF (0x%02x), ",pd); + break; + } + + /* call reference */ + + i++; + + len = buf[i] & 0x0f; + + switch(len) + { + case 1: + sprintf((pbuf+strlen(pbuf)), "cr=0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+1] & 0x80) ? "(from destination)" : "(from origination)"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "cr: LEN=%d %s 0x%02x 0x%02x, ", len, (buf[i+1] & 0x80) ? "org" : "dst", (buf[i+1] & 0x7f), (buf[i+2] & 0x7f)); + break; + } + + i += (len+1); + + /* message type */ + + sprintf((pbuf+strlen(pbuf)), "message="); + + if(pd == 0x40) /* protocol discriminator N0 */ + { + switch(buf[i]) + { + case 0x61: + sprintf((pbuf+strlen(pbuf)), "REGISTER INDICATION: "); + break; + case 0x62: + sprintf((pbuf+strlen(pbuf)), "CANCEL INDICATION: "); + break; + case 0x63: + sprintf((pbuf+strlen(pbuf)), "FACILITY STATUS: "); + break; + case 0x64: + sprintf((pbuf+strlen(pbuf)), "STATUS ACKNOWLEDGE: "); + break; + case 0x65: + sprintf((pbuf+strlen(pbuf)), "STATUS REJECT: "); + break; + case 0x66: + sprintf((pbuf+strlen(pbuf)), "FACILITY INFORMATION: "); + break; + case 0x67: + sprintf((pbuf+strlen(pbuf)), "INFORMATION ACKNOWLEDGE: "); + break; + case 0x68: + sprintf((pbuf+strlen(pbuf)), "INFORMATION REJECT: "); + break; + case 0x75: + sprintf((pbuf+strlen(pbuf)), "CLOSE: "); + break; + case 0x77: + sprintf((pbuf+strlen(pbuf)), "CLOSE ACKNOWLEDGE: "); + break; + default: + sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x40 MSG=0x%02x, ", buf[i]); + break; + } + } + else if(pd == 0x41) + { + switch(buf[i]) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "ESCAPE: "); + break; + case 0x01: + sprintf((pbuf+strlen(pbuf)), "ALERT: "); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "CALL SENT: "); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "CONNECT: "); + break; + case 0x0f: + sprintf((pbuf+strlen(pbuf)), "CONNECT ACKNOWLEDGE: "); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "SETUP: "); + break; + case 0x0d: + sprintf((pbuf+strlen(pbuf)), "SETUP ACKNOWLEDGE: "); + break; + + case 0x26: + sprintf((pbuf+strlen(pbuf)), "RESUME: "); + break; + case 0x2e: + sprintf((pbuf+strlen(pbuf)), "RESUME ACKNOWLEDGE: "); + break; + case 0x22: + sprintf((pbuf+strlen(pbuf)), "RESUME REJECT: "); + break; + case 0x25: + sprintf((pbuf+strlen(pbuf)), "SUSPEND: "); + break; + case 0x2d: + sprintf((pbuf+strlen(pbuf)), "SUSPEND ACKNOWLEDGE: "); + break; + case 0x21: + sprintf((pbuf+strlen(pbuf)), "SUSPEND REJECT: "); + break; + case 0x20: + sprintf((pbuf+strlen(pbuf)), "USER INFORMATION: "); + break; + + case 0x40: + sprintf((pbuf+strlen(pbuf)), "DETACH"); + break; + case 0x45: + sprintf((pbuf+strlen(pbuf)), "DISCONNECT: "); + break; + case 0x4d: + sprintf((pbuf+strlen(pbuf)), "RELEASE: "); + break; + case 0x5a: + sprintf((pbuf+strlen(pbuf)), "RELEASE ACKNOWLEDGE"); + break; + + case 0x6e: + sprintf((pbuf+strlen(pbuf)), "CANCEL ACKNOWLEDGE: "); + break; + case 0x67: + sprintf((pbuf+strlen(pbuf)), "CANCEL REJECT: "); + break; + case 0x69: + sprintf((pbuf+strlen(pbuf)), "CONGESTION CONTROL: "); + break; + case 0x60: + sprintf((pbuf+strlen(pbuf)), "FACILITY: "); + break; + case 0x68: + sprintf((pbuf+strlen(pbuf)), "FACILITY ACKNOWLEDGE: "); + break; + case 0x66: + sprintf((pbuf+strlen(pbuf)), "FACILITY CANCEL: "); + break; + case 0x64: + sprintf((pbuf+strlen(pbuf)), "FACILITY REGISTER: "); + break; + case 0x65: + sprintf((pbuf+strlen(pbuf)), "FACILITY REJECT: "); + break; + case 0x6d: + sprintf((pbuf+strlen(pbuf)), "INFORMATION: "); + break; + case 0x6c: + sprintf((pbuf+strlen(pbuf)), "REGISTER ACKNOWLEDGE: "); + break; + case 0x6f: + sprintf((pbuf+strlen(pbuf)), "REGISTER REJECT: "); + break; + case 0x63: + sprintf((pbuf+strlen(pbuf)), "STATUS: "); + break; + + default: + sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x41 MSG=0x%02x, ", buf[i]); + break; + } + } + else + { + sprintf((pbuf+strlen(pbuf)), "ERROR: PD=0x%02x MSG=0x%02x, ", pd, buf[i]); + } + + /* other information elements */ + + i++; + + for (; i < n;) + { + sprintf((pbuf+strlen(pbuf)), "\n "); + + if(buf[i] & 0x80) + { + /* single octett info element */ + + switch(buf[i] & 0x70) + { + case 0x00: /* reserved */ + sprintf((pbuf+strlen(pbuf)), "[reserved single octett info]"); + break; + + case 0x10: /* shift */ + oldcodeset = codeset; + codeset = buf[i] & 0x07; + if(buf[i] & 0x08) + codelock = 0; + else + codelock = 1; + sprintf((pbuf+strlen(pbuf)), "[shift: codeset=%d lock=%d]", codeset, codelock); + break; + + case 0x20: /* more data */ + sprintf((pbuf+strlen(pbuf)), "[more data]"); + break; + + case 0x30: /* congestion level */ + sprintf((pbuf+strlen(pbuf)), "[congestion level = %d]", buf[i] & 0x0f); + break; + + default: + sprintf((pbuf+strlen(pbuf)), "[UNDEF SINGLE OCTET ELEMENT 0x%02x]", buf[i]); + break; + } + + i++; /* next */ + + } + else + { + /* variable length info element */ + + if(codeset == 0) + { + switch(buf[i]) + { + case 0x08: + sprintf((pbuf+strlen(pbuf)), "[cause: "); + i += p_1tr6cause(pbuf, &buf[i]); + goto next; + break; + + case 0x0c: + sprintf((pbuf+strlen(pbuf)), "[connected address: "); + i += p_1tr6address(pbuf, &buf[i]); + goto next; + break; + + case 0x10: + sprintf((pbuf+strlen(pbuf)), "[call identity: "); + break; + case 0x18: + sprintf((pbuf+strlen(pbuf)), "[channel id: channel="); + i += 2; + switch(buf[i] & 0x03) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "no channel"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "B-1"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "B-2"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "any channel"); + break; + } + if(buf[i] & 0x08) + sprintf((pbuf+strlen(pbuf)), " (exclusive)]"); + else + sprintf((pbuf+strlen(pbuf)), " (preferred)]"); + i++; + goto next; + break; + case 0x20: + sprintf((pbuf+strlen(pbuf)), "[network specific facilities: "); + i++; + len = buf[i]; + i+=2; + switch(buf[i]) + { + case 1: + sprintf((pbuf+strlen(pbuf)), "Sperre"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "AWS 1"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "AWS 2"); + break; + case 0xe: + sprintf((pbuf+strlen(pbuf)), "Konferenz"); + break; + case 0xf: + sprintf((pbuf+strlen(pbuf)), "B-Kan uebern."); + break; + case 0x10: + sprintf((pbuf+strlen(pbuf)), "aktvrg. ghlt. Vbdg."); + break; + case 0x11: + sprintf((pbuf+strlen(pbuf)), "3er Konf"); + break; + case 0x12: + sprintf((pbuf+strlen(pbuf)), "1seitg D/G Wechsel"); + break; + case 0x13: + sprintf((pbuf+strlen(pbuf)), "2seitig D/G Wechsel"); + break; + case 0x14: + sprintf((pbuf+strlen(pbuf)), "Rufnr. identifiz."); + break; + case 0x15: + sprintf((pbuf+strlen(pbuf)), "GBG"); + break; + case 0x17: + sprintf((pbuf+strlen(pbuf)), "ueberg. Ruf"); + break; + case 0x1a: + sprintf((pbuf+strlen(pbuf)), "um/weitergel. Ruf"); + break; + case 0x1b: + sprintf((pbuf+strlen(pbuf)), "unterdr. A-Rufnr."); + break; + case 0x1e: + sprintf((pbuf+strlen(pbuf)), "Verbdg. deaktivieren"); + break; + case 0x1d: + sprintf((pbuf+strlen(pbuf)), "Verbdg. aktivieren"); + break; + case 0x1f: + sprintf((pbuf+strlen(pbuf)), "SPV"); + break; + case 0x23: + sprintf((pbuf+strlen(pbuf)), "Rueckw. 2seitg. DW"); + break; + case 0x24: + sprintf((pbuf+strlen(pbuf)), "Anrufumltg. priv. Netz"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "undefined"); + break; + } + i++; + sprintf((pbuf+strlen(pbuf)), ", serv=%d", buf[i]); + i++; + sprintf((pbuf+strlen(pbuf)), ", ainfo=%d", buf[i]); + i++; + len-=4; + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]); + } + sprintf((pbuf+strlen(pbuf)),"]"); + i += j; + goto next; + break; + case 0x28: + sprintf((pbuf+strlen(pbuf)), "[display: "); + break; + case 0x2c: + sprintf((pbuf+strlen(pbuf)), "[keypad: "); + break; + case 0x6c: + sprintf((pbuf+strlen(pbuf)), "[origination address: "); + i += p_1tr6address(pbuf, &buf[i]); + goto next; + break; + case 0x70: + sprintf((pbuf+strlen(pbuf)), "[destination address: "); + i += p_1tr6address(pbuf, &buf[i]); + goto next; + break; + case 0x7e: + sprintf((pbuf+strlen(pbuf)), "[user-user information: "); + break; + case 0x7f: + sprintf((pbuf+strlen(pbuf)), "[reserved: "); + break; + default: + sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID"); + break; + } + } + else if(codeset == 6) + { + switch(buf[i]) + { + case 0x01: + sprintf((pbuf+strlen(pbuf)), "[service ind: serv="); + i+= 2; + switch(buf[i]) + { + case 0x01: + sprintf((pbuf+strlen(pbuf)), "phone"); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "a/b"); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "X.21"); + break; + case 0x04: + sprintf((pbuf+strlen(pbuf)), "fax g4"); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "btx"); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "64k data"); + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "X.25"); + break; + case 0x09: + sprintf((pbuf+strlen(pbuf)), "teletex"); + break; + case 0x0a: + sprintf((pbuf+strlen(pbuf)), "mixed"); + break; + case 0x0d: + sprintf((pbuf+strlen(pbuf)), "temex"); + break; + case 0x0e: + sprintf((pbuf+strlen(pbuf)), "picturephone"); + break; + case 0x0f: + sprintf((pbuf+strlen(pbuf)), "btx (new)"); + break; + case 0x10: + sprintf((pbuf+strlen(pbuf)), "videophone"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "undefined"); + break; + } + i++; + sprintf((pbuf+strlen(pbuf)), ", ainfo=0x%02x]", buf[i]); + i++; + goto next; + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "[charging information: "); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "[date: "); + i++; + len = buf[i]; + i++; + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]); + } + sprintf((pbuf+strlen(pbuf)),"]"); + i += j; + goto next; + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "[facility select: "); + break; + case 0x06: + sprintf((pbuf+strlen(pbuf)), "[status of facilities: "); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "[status of called party: "); + i+=2; + switch(buf[i]) + { + case 1: + sprintf((pbuf+strlen(pbuf)), "no information]"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "is being called]"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "undefined (0x%02x)]", buf[i]); + break; + } + i++; + goto next; + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "[additional tx attributes: "); + i++; + len = buf[i]; + i++; + for(j = 0; j < len; j++) + { + switch(buf[j+i] &0x70) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "no satellite link"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "one satellite link"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "two satellite links"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "three satellite links"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "undefined value"); + break; + } + if(buf[j+i] & 0x80) + sprintf((pbuf+strlen(pbuf)),"(flag=req)]"); + else + sprintf((pbuf+strlen(pbuf)),"(flag=ind)]"); + } + i += j; + goto next; + break; + default: + sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID"); + break; + } + } + else + { + sprintf((pbuf+strlen(pbuf)), "[ILLEGAL CODESET = 0x%02x", codeset); + } + + i++; /* index -> length */ + + len = buf[i]; + + i++; /* index -> 1st param */ + + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]); + } + + sprintf((pbuf+strlen(pbuf)),"]"); + + i += len; + +next: + + if(!codelock && (codeset != oldcodeset)) + codeset = oldcodeset; + } + } + sprintf((pbuf+strlen(pbuf)),"\n"); +} + +/*---------------------------------------------------------------------------* + * decode and print the cause + *---------------------------------------------------------------------------*/ +static int +p_1tr6cause(char *pbuf, unsigned char buf[]) +{ + int j; + int len; + int i = 0; + + i++; /* index -> length */ + + len = buf[i]; + + switch(len) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "%s", print_cause_1tr6(0)); + break; + case 1: + i++; + sprintf((pbuf+strlen(pbuf)), "%s", print_cause_1tr6(buf[i] & 0x7f)); + break; + case 2: + i++; + sprintf((pbuf+strlen(pbuf)), "%s, location: ", print_cause_1tr6(buf[i] & 0x7f)); + i++; + switch(buf[i] & 0x0f) + { + case 0x04: + sprintf((pbuf+strlen(pbuf)), "public network"); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "private network"); + break; + case 0x0f: + sprintf((pbuf+strlen(pbuf)), "no information"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + break; + default: + i++; /* index -> length */ + len = buf[i]; + i++; /* index -> 1st param */ + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]); + } + break; + } + i++; + sprintf((pbuf+strlen(pbuf)),"]"); + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the ISDN (telephone) number + *---------------------------------------------------------------------------*/ +static int +p_1tr6address(char *pbuf, unsigned char buf[]) +{ + int j; + int len; + int i = 0; + int tp; + + i++; /* index -> length */ + len = buf[i]; + i++; /* index -> 1st param */ + tp = buf[i]; + + i++; + len--; + + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]); + } + + switch((tp & 0x70) >> 4) + { + case 0: + sprintf((pbuf+strlen(pbuf)), " (type=unknown, "); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), " (type=international, "); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), " (type=national, "); + break; + default: + sprintf((pbuf+strlen(pbuf)), " (type=%d, ", ((tp & 0x70) >> 4)); + break; + } + + switch(tp & 0x0f) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "plan=unknown)"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "plan=ISDN)"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "plan=%d)", (tp & 0x0f)); + break; + } + + sprintf((pbuf+strlen(pbuf)),"]"); + + i += j; + + return(i); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/Makefile b/usr.sbin/i4b/isdntrace/Makefile new file mode 100644 index 0000000..150c18d --- /dev/null +++ b/usr.sbin/i4b/isdntrace/Makefile @@ -0,0 +1,8 @@ +PROG = isdntrace +SRCS = q921.c q931.c q931_util.c q932_fac.c 1tr6.c trace.c \ + pcause_1tr6.c pcause_q850.c +#CFLAGS += -Wall -g +MAN8 = isdntrace.8 + +.include <bsd.prog.mk> + diff --git a/usr.sbin/i4b/isdntrace/cable.txt b/usr.sbin/i4b/isdntrace/cable.txt new file mode 100644 index 0000000..890d8d4 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/cable.txt @@ -0,0 +1,60 @@ + *--------------------------------------------------------------------------- + * + * Custom cable to trace an ISDN S0 bus with two passive (!) ISDN boards + * --------------------------------------------------------------------- + * + * $Id: cable.txt,v 1.2 1998/01/22 20:39:49 hm Exp $ + * + * last edit-date: [Thu Jan 22 19:57:50 1998] + * + * -hm documentation of analyze mode + * + *---------------------------------------------------------------------------*/ + +The cable consists of a RJ-45 plug with both tx and rx connected and +two jacks; the tx cables from the plug are wired to one jack and the +rx cables from the plug are wired to the other jack. + +The computer must be equipped with two (!) supported passive cards and +the cable from one card is plugged into one of the jacks while the cable +to from the other card is plugged into the other jack. + +Now one card monitors the tx part of the S0 bus and the other card +monitors the rx part. + +Which card functions as the rx side and which as the tx side can be +specified as options to the isdntrace utility (-R and -T) which has +to be run in analyzer mode (-a) to support this configuration. + + + 1 + 2 + 3 + +--------------4 receiving-side board + S0-bus +--|--------------5 in computer (jack for + to analyze | | 6 cable to passive controller) + 8 | | 7 + 7 | | 8 + transmit - 6------------|--|--+ + receive - 5------------+ | | + receive + 4---------------+ | + transmit + 3------------+ | + 2 | | 1 + 1 | | 2 + plug into | | 3 + S0 bus +-----|-----------4 transmitting-side board + +-----------5 in computer (jack for + 6 cable to passive controller) + 7 + 8 + + + + RJ-45 plug RJ-45 jack + view from the front view from the front + cable goes out to the rear + + /--------- / ---------- + | 87654321 | | 12345678 | + |__ __|/ |/_ /_| + |____|/ |/___| diff --git a/usr.sbin/i4b/isdntrace/isdntrace.8 b/usr.sbin/i4b/isdntrace/isdntrace.8 new file mode 100644 index 0000000..62c5d07 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/isdntrace.8 @@ -0,0 +1,205 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isdntrace.8,v 1.9 1998/12/05 18:04:10 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:18:59 1998] +.\" +.Dd October 19, 1998 +.Dt isdntrace 8 +.Sh NAME +.Nm isdntrace +.Nd isdn4bsd ISDN protocol trace utility +.Sh SYNOPSIS +.Nm isdntrace +.Op Fl a +.Op Fl b +.Op Fl d +.Op Fl f Ar filename +.Op Fl h +.Op Fl i +.Op Fl l +.Op Fl n Ar number +.Op Fl o +.Op Fl p Ar filename +.Op Fl r +.Op Fl u Ar number +.Op Fl B +.Op Fl F +.Op Fl P +.Op Fl R Ar unit +.Op Fl T Ar unit +.Sh DESCRIPTION +.Nm isdntrace +is part of the isdn4bsd package and is used to provide the user with a +mnemonic display of the layers 1, 2 and 3 protocol activities on +the D channel and hex dump of the B channel(s) activities. +.Pp +Together with two passive supported cards and an easy to build cable it can +also be used to monitor the complete traffic on a S0 bus providing S0 bus +analyzer features. +.Pp +The +.Nm +utility is only available for passive supported cards. +.Pp +The following options can be used: +.Bl -tag -width Ds +.It Fl a +Run +.Nm +in analyzer mode by using two passive cards and a custom cable which can +be build as described in the file +.Em cable.txt +in the isdn4bsd source distribution. One card acts as a receiver for the +transmitting direction on the S0 bus while the other card acts as a receiver +for the receiving direction on the S0 bus. Complete traffic monitoring is +possible using this setup. +.It Fl b +switch B channel tracing on (default off). +.It Fl d +switch D channel tracing off (default on). +.It Fl f +Use +.Ar filename +as the name of a file into which to write tracing output (default filename is +isdntrace<n> where n is the number of the unit to trace). +.It Fl h +switch display of header off (default on). +.It Fl i +print layer 1 (I.430) INFO signals to monitor layer 1 activity (default off). +.It Fl l +switch displaying of Layer 2 (Q.921) frames off (default on). +.It Fl n +This option takes a numeric argument specifying the minimum +frame size in octetts a frame must have to be displayed. (default 0) +.It Fl o +switch off writing trace output to a file (default on). +.It Fl p +Use +.Ar filename +as the name of a file used for the -B and -P options (default filename +is isdntracebin<n> where n is the number of the unit to trace). +.It Fl r +Switch off printing a raw hexadecimal dump of the packets preceding +the decoded protocol information (default on). +.It Fl u +Use +.Ar number +as the unit number of the controller card to trace (default 0). +.It Fl B +Write undecoded binary trace data to a file for later or remote +analyzing (default off). +.It Fl F +This option can only be used when option -P (playback from binary data file) +is used. The -F option causes playback not to stop at end of file but rather +to wait for additional data to be available from the input file. +.Pp +This option is useful when trace data is accumulated in binary format (to +save disk space) but a monitoring functionality is desired. +(default off). +.It Fl P +Read undecoded binary trace data from file instead from device (default off). +.It Fl R +Use +.Ar unit +as the receiving interface unit number in analyze mode. +.It Fl T +Use +.Ar unit +as the transmitting interface unit number in analyze mode. +.El +.Pp +When the USR1 signal is sent to a +.Nm +process, the currently used logfiles are reopened, so that logfile +rotation becomes possible. +.Pp +The trace output should be obvious. It is very handy to have the following +standard texts available when tracing ISDN protocols: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar I.430 +ISDN BRI layer 1 protocol description. +.It Ar Q.921 +ISDN D-channel layer 2 protocol description. +.It Ar Q.931 +ISDN D-channel layer 3 protocol description. +.It Ar 1TR6 +German-specific ISDN layer 3 protocol description. (NOTICE: decoding +of the 1TR6 protocol is included but not supported since i dont have +any longer access to a 1TR6 based ISDN installation.) +.El +.Pp + +.Nm Isdntrace +automatically detects the layer 3 protocol being used by looking at the +Protocol Discriminator (see: Q.931/1993 pp. 53). +.Pp + + +.Sh FILES +.Bl -tag -width daddeldi -compact +.It Pa /dev/i4btrc<n> +The devicefile(s) used to get the trace messages for ISDN card unit <n> +out of the kernel. +.El + +.Sh EXAMPLES +The command: +.Bd -literal -offset indent +isdntrace -f /var/tmp/isdn.trace +.Ed +.Pp +will start D channel tracing on passive controller 0 with all except B +channel tracing enabled and logs everything into the output file +/tmp/isdn.trace. + +.Sh SEE ALSO +.Xr isdnd 8 + +.Sh BUGS +Still some or more left. + +.Sh STANDARDS +ITU Recommendations I.430, Q.920, Q.921, Q.930, Q.931 +.Pp +FTZ Richtlinie 1TR3, Band III +.Pp +ITU Recommendation Q.932 (03/93), Q.950 (03/93) +.Pp +ETSI Recommendation ETS 300 179 (10/92), ETS 300 180 (10/92) +.Pp +ETSI Recommendation ETS 300 181 (04/93), ETS 300 182 (04/93) +.Pp +ITU Recommendation X.208, X.209 + +.Sh AUTHOR +The +.Nm +utility was written by Gary Jennejohn and Hellmuth Michaelis. +.Pp +This manual page was written by Hellmuth Michaelis, he can be reached +at hm@kts.org. + diff --git a/usr.sbin/i4b/isdntrace/pcause_1tr6.c b/usr.sbin/i4b/isdntrace/pcause_1tr6.c new file mode 100644 index 0000000..42f244d --- /dev/null +++ b/usr.sbin/i4b/isdntrace/pcause_1tr6.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * printing cause values + * --------------------- + * + * $Id: pcause_1tr6.c,v 1.4 1998/12/23 10:03:55 hm Exp $ + * + * last edit-date: [Wed Dec 23 10:57:11 1998] + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" +#include "pcause_1tr6.h" + +char * +print_cause_1tr6(unsigned char code) +{ + static char error_message[120]; + char *e; + + switch(code) + { + case CAUSE_1TR6_SHUTDN: + e = "normal D-channel shutdown"; + break; + + case CAUSE_1TR6_ICRV: + e = "invalid call reference value"; + break; + + case CAUSE_1TR6_BSNI: + e = "bearer service not implemented"; + break; + + case CAUSE_1TR6_CIDNE: + e = "call identity does not exist"; + break; + + case CAUSE_1TR6_CIIU: + e = "call identity in use"; + break; + + case CAUSE_1TR6_NCA: + e = "no channel available"; + break; + + case CAUSE_1TR6_RFNI: + e = "requested facility not implemented"; + break; + + case CAUSE_1TR6_RFNS: + e = "requested facility not subscribed"; + break; + + case CAUSE_1TR6_OCB: + e = "outgoing calls barred"; + break; + + case CAUSE_1TR6_UAB: + e = "user access busy"; + break; + + case CAUSE_1TR6_NECUG: + e = "non existent CUG"; + break; + + case CAUSE_1TR6_NECUG1: + e = "non existent CUG"; + break; + + case CAUSE_1TR6_SPV: + e = "kommunikationsbeziehung als SPV nicht erlaubt"; + break; + + case CAUSE_1TR6_DNO: + e = "destination not obtainable"; + break; + + case CAUSE_1TR6_NC: + e = "number changed"; + break; + + case CAUSE_1TR6_OOO: + e = "out of order"; + break; + + case CAUSE_1TR6_NUR: + e = "no user responding"; + break; + + case CAUSE_1TR6_UB: + e = "user busy"; + break; + + case CAUSE_1TR6_ICB: + e = "incoming calls barred"; + break; + + case CAUSE_1TR6_CR: + e = "call rejected"; + break; + + case CAUSE_1TR6_NCO: + e = "network congestion"; + break; + + case CAUSE_1TR6_RUI: + e = "remote user initiated"; + break; + + case CAUSE_1TR6_LPE: + e = "local procedure error"; + break; + + case CAUSE_1TR6_RPE: + e = "remote procedure error"; + break; + + case CAUSE_1TR6_RUS: + e = "remote user suspended"; + break; + + case CAUSE_1TR6_RUR: + e = "remote user resumed"; + break; + + case CAUSE_1TR6_UIDL: + e = "user info discharded locally"; + break; + + default: + e = "UNKNOWN error occured"; + break; + } + + sprintf(error_message, "0x%02x: %s", code & 0x7f, e); + return(error_message); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/pcause_1tr6.h b/usr.sbin/i4b/isdntrace/pcause_1tr6.h new file mode 100644 index 0000000..f327cc7 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/pcause_1tr6.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcause1tr6.h - 1TR6 causes definitions + * -------------------------------------- + * + * $Id: pcause_1tr6.h,v 1.3 1998/12/05 18:04:13 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:19:39 1998] + * + *---------------------------------------------------------------------------*/ + +char *print_cause_1tr6(unsigned char code); + +/* 1TR6 protocol causes */ + +#define CAUSE_1TR6_SHUTDN 0x00 /* normal D-channel shutdown */ +#define CAUSE_1TR6_ICRV 0x01 /* invalid call reference value */ +#define CAUSE_1TR6_BSNI 0x03 /* bearer service not implemented */ +#define CAUSE_1TR6_CIDNE 0x07 /* call identity does not exist */ +#define CAUSE_1TR6_CIIU 0x08 /* call identity in use */ +#define CAUSE_1TR6_NCA 0x0A /* no channel available */ +#define CAUSE_1TR6_RFNI 0x10 /* requested facility not implemented */ +#define CAUSE_1TR6_RFNS 0x11 /* requested facility not subscribed */ +#define CAUSE_1TR6_OCB 0x20 /* outgoing calls barred */ +#define CAUSE_1TR6_UAB 0x21 /* user access busy */ +#define CAUSE_1TR6_NECUG 0x22 /* non existent CUG */ +#define CAUSE_1TR6_NECUG1 0x23 /* non existent CUG */ +#define CAUSE_1TR6_SPV 0x25 /* kommunikationsbeziehung als SPV nicht erlaubt */ +#define CAUSE_1TR6_DNO 0x35 /* destination not obtainable */ +#define CAUSE_1TR6_NC 0x38 /* number changed */ +#define CAUSE_1TR6_OOO 0x39 /* out of order */ +#define CAUSE_1TR6_NUR 0x3A /* no user responding */ +#define CAUSE_1TR6_UB 0x3B /* user busy */ +#define CAUSE_1TR6_ICB 0x3D /* incoming calls barred */ +#define CAUSE_1TR6_CR 0x3E /* call rejected */ +#define CAUSE_1TR6_NCO 0x59 /* network congestion */ +#define CAUSE_1TR6_RUI 0x5A /* remote user initiated */ +#define CAUSE_1TR6_LPE 0x70 /* local procedure error */ +#define CAUSE_1TR6_RPE 0x71 /* remote procedure error */ +#define CAUSE_1TR6_RUS 0x72 /* remote user suspended */ +#define CAUSE_1TR6_RUR 0x73 /* remote user resumed */ +#define CAUSE_1TR6_UIDL 0x7F /* user info discharded locally */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/pcause_q850.c b/usr.sbin/i4b/isdntrace/pcause_q850.c new file mode 100644 index 0000000..1c98388 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/pcause_q850.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * printing cause values + * --------------------- + * + * $Id: pcause_q850.c,v 1.4 1998/12/23 10:03:55 hm Exp $ + * + * last edit-date: [Wed Dec 23 10:57:36 1998] + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" +#include "pcause_q850.h" + +char * +print_cause_q850(unsigned char code) +{ + static char error_message[120]; + char *e; + + switch(code) + { + case CAUSE_Q850_SHUTDN: + e = "normal D-channel shutdown"; + break; + + case CAUSE_Q850_NUNALLC: + e = "Unallocated (unassigned) number"; + break; + + case CAUSE_Q850_NRTTN: + e = "No route to specified transit network"; + break; + + case CAUSE_Q850_NRTDST: + e = "No route to destination"; + break; + + case CAUSE_Q850_SSINFTN: + e = "Send special information tone"; + break; + + case CAUSE_Q850_MDIALTP: + e = "Misdialled trunk prefix"; + break; + + case CAUSE_Q850_CHUNACC: + e = "Channel unacceptable"; + break; + + case CAUSE_Q850_CALLAWD: + e = "Call awarded and being delivered in an established channel"; + break; + + case CAUSE_Q850_PREEMPT: + e = "Preemption"; + break; + + case CAUSE_Q850_PREECRR: + e = "Preemption - circuit reserved for reuse"; + break; + + case CAUSE_Q850_NCCLR: + e = "Normal call clearing"; + break; + + case CAUSE_Q850_USRBSY: + e = "User busy"; + break; + + case CAUSE_Q850_NOUSRRSP: + e = "No user responding"; + break; + + case CAUSE_Q850_NOANSWR: + e = "No answer from user (user alerted)"; + break; + + case CAUSE_Q850_SUBSABS: + e = "Subscriber absent"; + break; + + case CAUSE_Q850_CALLREJ: + e = "Call rejected"; + break; + + case CAUSE_Q850_NUCHNG: + e = "Number changed"; + break; + + case CAUSE_Q850_NONSELUC: + e = "Non-selected user clearing"; + break; + + case CAUSE_Q850_DSTOOORDR: + e = "Destination out of order"; + break; + + case CAUSE_Q850_INVNUFMT: + e = "Invalid number format"; + break; + + case CAUSE_Q850_FACREJ: + e = "Facility rejected"; + break; + + case CAUSE_Q850_STENQRSP: + e = "Response to STATUS ENQUIRY"; + break; + + case CAUSE_Q850_NORMUNSP: + e = "Normal, unspecified"; + break; + + case CAUSE_Q850_NOCAVAIL: + e = "No circuit / channel available"; + break; + + case CAUSE_Q850_NETOOORDR: + e = "Network out of order"; + break; + + case CAUSE_Q850_PFMCDOOSERV: + e = "Permanent frame mode connection out of service"; + break; + + case CAUSE_Q850_PFMCOPER: + e = "Permanent frame mode connection operational"; + break; + + case CAUSE_Q850_TMPFAIL: + e = "Temporary failure"; + break; + + case CAUSE_Q850_SWEQCONG: + e = "Switching equipment congestion"; + break; + + case CAUSE_Q850_ACCINFDIS: + e = "Access information discarded"; + break; + + case CAUSE_Q850_REQCNOTAV: + e = "Requested circuit/channel not available"; + break; + + case CAUSE_Q850_PRECALBLK: + e = "Precedence call blocked"; + break; + + case CAUSE_Q850_RESUNAVAIL: + e = "Resources unavailable, unspecified"; + break; + + case CAUSE_Q850_QOSUNAVAIL: + e = "Quality of service unavailable"; + break; + + case CAUSE_Q850_REQSERVNS: + e = "Requested facility not subscribed"; + break; + + case CAUSE_Q850_OCBARRCUG: + e = "Outgoing calls barred within CUG"; + break; + + case CAUSE_Q850_ICBARRCUG: + e = "Incoming calls barred within CUG"; + break; + + case CAUSE_Q850_BCAPNAUTH: + e = "Bearer capability not authorized"; + break; + + case CAUSE_Q850_BCAPNAVAIL: + e = "Bearer capability not presently available"; + break; + + case CAUSE_Q850_INCSTOACISC: + e = "Inconsistenciy in designated outg. access info and subscriber class"; + break; + + case CAUSE_Q850_SOONOTAVAIL: + e = "Service or option not available, unspecified"; + break; + + case CAUSE_Q850_BCAPNOTIMPL: + e = "Bearer capability not implemented"; + break; + + case CAUSE_Q850_CHTYPNIMPL: + e = "Channel type not implemented"; + break; + + case CAUSE_Q850_REQFACNIMPL: + e = "Requested facility not implemented"; + break; + + case CAUSE_Q850_ORDINBCAVL: + e = "Only restricted digital information bearer capability is available"; + break; + + case CAUSE_Q850_SOONOTIMPL: + e = "Service or option not implemented, unspecified"; + break; + + case CAUSE_Q850_INVCLRFVAL: + e = "Invalid call reference value"; + break; + + case CAUSE_Q850_IDCHDNOEX: + e = "Identified channel does not exist"; + break; + + case CAUSE_Q850_SUSCAEXIN: + e = "A suspended call exists, but this call identity does not"; + break; + + case CAUSE_Q850_CLIDINUSE: + e = "Call identity in use"; + break; + + case CAUSE_Q850_NOCLSUSP: + e = "No call suspended"; + break; + + case CAUSE_Q850_CLIDCLRD: + e = "Call having the requested call identity has been cleared"; + break; + + case CAUSE_Q850_UNOTMEMCUG: + e = "User not member of CUG"; + break; + + case CAUSE_Q850_INCDEST: + e = "Incompatible destination"; + break; + + case CAUSE_Q850_NONEXCUG: + e = "Non-existent CUG"; + break; + + case CAUSE_Q850_INVNTWSEL: + e = "Invalid transit network selection"; + break; + + case CAUSE_Q850_INVMSG: + e = "Invalid message, unspecified"; + break; + + case CAUSE_Q850_MIEMISS: + e = "Mandatory information element is missing"; + break; + + case CAUSE_Q850_MSGTNI: + e = "Message type non-existent or not implemented"; + break; + + case CAUSE_Q850_MSGNCMPT: + e = "Msg incompatible with call state/message type non-existent/not implemented"; + break; + + case CAUSE_Q850_IENENI: + e = "Information element/parameter non-existent or not implemented"; + break; + + case CAUSE_Q850_INVIEC: + e = "Invalid information element contents"; + break; + + case CAUSE_Q850_MSGNCWCS: + e = "Message not compatible with call state"; + break; + + case CAUSE_Q850_RECOTIMEXP: + e = "Recovery on timer expiry"; + break; + + case CAUSE_Q850_PARMNENIPO: + e = "Parameter non-existent or not implemented, passed on"; + break; + + case CAUSE_Q850_MSGUNRDPRM: + e = "Message with unrecognized parameter, discarded"; + break; + + case CAUSE_Q850_PROTERR: + e = "Protocol error, unspecified"; + break; + + case CAUSE_Q850_INTWRKU: + e = "Interworking, unspecified"; + break; + + default: + e = "ERROR, unknown cause value!"; + break; + } + + sprintf(error_message, "%d: %s (Q.850)", code, e); + return(error_message); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/pcause_q850.h b/usr.sbin/i4b/isdntrace/pcause_q850.h new file mode 100644 index 0000000..a6b947f --- /dev/null +++ b/usr.sbin/i4b/isdntrace/pcause_q850.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * pcauseq850.h - Q.850 causes definitions + * --------------------------------------- + * + * $Id: pcause_q850.h,v 1.3 1998/12/05 18:04:18 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:20:05 1998] + * + *---------------------------------------------------------------------------*/ + +char *print_cause_q850(unsigned char code); + +/* Q.850 causes */ + +#define CAUSE_Q850_SHUTDN 0x00 /* normal D-channel shutdown */ +#define CAUSE_Q850_NUNALLC 0x01 /* Unallocated (unassigned) number */ +#define CAUSE_Q850_NRTTN 0x02 /* No route to specified transit network */ +#define CAUSE_Q850_NRTDST 0x03 /* No route to destination */ +#define CAUSE_Q850_SSINFTN 0x04 /* Send special information tone */ +#define CAUSE_Q850_MDIALTP 0x05 /* Misdialled trunk prefix */ +#define CAUSE_Q850_CHUNACC 0x06 /* Channel unacceptable */ +#define CAUSE_Q850_CALLAWD 0x07 /* Call awarded and being delivered in an established channel */ +#define CAUSE_Q850_PREEMPT 0x08 /* Preemption */ +#define CAUSE_Q850_PREECRR 0x09 /* Preemption - circuit reserved for reuse */ +#define CAUSE_Q850_NCCLR 0x10 /* Normal call clearing */ +#define CAUSE_Q850_USRBSY 0x11 /* User busy */ +#define CAUSE_Q850_NOUSRRSP 0x12 /* No user responding */ +#define CAUSE_Q850_NOANSWR 0x13 /* No answer from user (user alerted) */ +#define CAUSE_Q850_SUBSABS 0x14 /* Subscriber absent */ +#define CAUSE_Q850_CALLREJ 0x15 /* Call rejected */ +#define CAUSE_Q850_NUCHNG 0x16 /* Number changed */ +#define CAUSE_Q850_NONSELUC 0x1A /* Non-selected user clearing */ +#define CAUSE_Q850_DSTOOORDR 0x1B /* Destination out of order */ +#define CAUSE_Q850_INVNUFMT 0x1C /* Invalid number format */ +#define CAUSE_Q850_FACREJ 0x1D /* Facility rejected */ +#define CAUSE_Q850_STENQRSP 0x1E /* Response to STATUS ENQUIRY */ +#define CAUSE_Q850_NORMUNSP 0x1F /* Normal, unspecified */ +#define CAUSE_Q850_NOCAVAIL 0x22 /* No circuit / channel available */ +#define CAUSE_Q850_NETOOORDR 0x26 /* Network out of order */ +#define CAUSE_Q850_PFMCDOOSERV 0x27 /* Permanent frame mode connection out of service */ +#define CAUSE_Q850_PFMCOPER 0x28 /* Permanent frame mode connection operational */ +#define CAUSE_Q850_TMPFAIL 0x29 /* Temporary failure */ +#define CAUSE_Q850_SWEQCONG 0x2A /* Switching equipment congestion */ +#define CAUSE_Q850_ACCINFDIS 0x2B /* Access information discarded */ +#define CAUSE_Q850_REQCNOTAV 0x2C /* Requested circuit/channel not available */ +#define CAUSE_Q850_PRECALBLK 0x2E /* Precedence call blocked */ +#define CAUSE_Q850_RESUNAVAIL 0x2F /* Resources unavailable, unspecified */ +#define CAUSE_Q850_QOSUNAVAIL 0x31 /* Quality of service unavailable */ +#define CAUSE_Q850_REQSERVNS 0x32 /* Requested facility not subscribed */ +#define CAUSE_Q850_OCBARRCUG 0x35 /* Outgoing calls barred within CUG */ +#define CAUSE_Q850_ICBARRCUG 0x36 /* Incoming calls barred within CUG */ +#define CAUSE_Q850_BCAPNAUTH 0x39 /* Bearer capability not authorized */ +#define CAUSE_Q850_BCAPNAVAIL 0x3A /* Bearer capability not presently available */ +#define CAUSE_Q850_INCSTOACISC 0x3E /* Inconsistenciy in designated outgoing access information and subscriber class */ +#define CAUSE_Q850_SOONOTAVAIL 0x3F /* Service or option not available, unspecified */ +#define CAUSE_Q850_BCAPNOTIMPL 0x41 /* Bearer capability not implemented */ +#define CAUSE_Q850_CHTYPNIMPL 0x42 /* Channel type not implemented */ +#define CAUSE_Q850_REQFACNIMPL 0x45 /* Requested facility not implemented */ +#define CAUSE_Q850_ORDINBCAVL 0x46 /* Only restricted digital information bearer capability is available */ +#define CAUSE_Q850_SOONOTIMPL 0x4F /* Service or option not implemented, unspecified */ +#define CAUSE_Q850_INVCLRFVAL 0x51 /* Invalid call reference value */ +#define CAUSE_Q850_IDCHDNOEX 0x52 /* Identified channel does not exist */ +#define CAUSE_Q850_SUSCAEXIN 0x53 /* A suspended call exists, but this call identity does not */ +#define CAUSE_Q850_CLIDINUSE 0x54 /* Call identity in use */ +#define CAUSE_Q850_NOCLSUSP 0x55 /* No call suspended */ +#define CAUSE_Q850_CLIDCLRD 0x56 /* Call having the requested call identity has been cleared */ +#define CAUSE_Q850_UNOTMEMCUG 0x57 /* User not member of CUG */ +#define CAUSE_Q850_INCDEST 0x58 /* Incompatible destination */ +#define CAUSE_Q850_NONEXCUG 0x5A /* Non-existent CUG */ +#define CAUSE_Q850_INVNTWSEL 0x5B /* Invalid transit network selection */ +#define CAUSE_Q850_INVMSG 0x5F /* Invalid message, unspecified */ +#define CAUSE_Q850_MIEMISS 0x60 /* Mandatory information element is missing */ +#define CAUSE_Q850_MSGTNI 0x61 /* Message type non-existent or not implemented */ +#define CAUSE_Q850_MSGNCMPT 0x62 /* Message not compatible with call state or message type non-existent or not implemented */ +#define CAUSE_Q850_IENENI 0x63 /* Information element/parameter non-existent or not implemented */ +#define CAUSE_Q850_INVIEC 0x64 /* Invalid information element contents */ +#define CAUSE_Q850_MSGNCWCS 0x65 /* Message not compatible with call state */ +#define CAUSE_Q850_RECOTIMEXP 0x66 /* Recovery on timer expiry */ +#define CAUSE_Q850_PARMNENIPO 0x67 /* Parameter non-existent or not implemented, passed on */ +#define CAUSE_Q850_MSGUNRDPRM 0x6E /* Message with unrecognized parameter, discarded */ +#define CAUSE_Q850_PROTERR 0x6F /* Protocol error, unspecified */ +#define CAUSE_Q850_INTWRKU 0x7F /* Interworking, unspecified */ + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/q921.c b/usr.sbin/i4b/isdntrace/q921.c new file mode 100644 index 0000000..df007a4 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/q921.c @@ -0,0 +1,275 @@ +/* + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *---------------------------------------------------------------------------* + * + * q.921.c - print Q.921 traces + * ---------------------------- + * + * $Id: q921.c,v 1.2 1998/04/16 15:27:02 hm Exp $ + * + * last edit-date: [Thu Apr 16 15:38:34 1998] + * + * -hm splitting + * -hm printing to buffer + * -hm slightly reformatted TEI management proc output + * -hm minor fixes + * -hm fixing response/command + * -hm fixing count off by one + * -hm dump only Q.921 part of frame + * -hm cleanup + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" + +/*---------------------------------------------------------------------------* + * decode LAPD (Q.921) protocol + *---------------------------------------------------------------------------*/ +int +decode_lapd(char *pbuf, int n, unsigned char *buf, int dir, int raw, int printit) +{ + int sap, tei, cmd, p_f; + int cnt = 0; + int i; + char locbuf[32000]; + char *lbufp = &locbuf[0]; + + *lbufp = '\0'; + *pbuf = '\0'; + + sap = (buf[0] >> 2) & 0x3f; + cnt++; + + tei = buf[1] >> 1; + cnt++; + + if(dir == FROM_TE) + cmd = !(buf[0] & 2); + else + cmd = buf[0] & 2; + + switch (sap) + { + /* SAPI control procedures */ + case 0: + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "Q921: SAP=%d (Call Control), %c, TEI=%d, ", sap, cmd?'C':'R', tei); + + if((buf[2] & 0x01) == 0) + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "I-Frame: "); + + p_f = buf [3] & 1; + + if(printit) + sprintf((lbufp+strlen(lbufp)), "N(S) %d N(R) %d P %d ", buf [2] >> 1, buf [3] >> 1, p_f); + + cnt += 2; + } + else if((buf[2] & 0x03) == 0x01) + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "S-Frame: "); + + p_f = buf [3] & 1; + cmd = buf [2] & 0x0c; + + if(printit) + { + if (cmd == 0) + sprintf((lbufp+strlen(lbufp)), "RR N(R) %d PF %d ", buf [3] >> 1, p_f); + if (cmd == 4) + sprintf((lbufp+strlen(lbufp)), "RNR N(R) %d PF %d ", buf [3] >> 1, p_f); + if (cmd == 8) + sprintf((lbufp+strlen(lbufp)), "REJ N(R) %d PF %d ", buf [3] >> 1, p_f); + } + cnt += 2; + } + else if((buf[2] & 0x03) == 0x03) + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "U-Frame: "); + + p_f = (buf [2] & 0x10) >> 4; + cmd = buf [2] & 0xec; + + if(printit) + { + if (cmd == 0x6c) + sprintf((lbufp+strlen(lbufp)), "SABME PF %d ", p_f); + if (cmd == 0x0c) + sprintf((lbufp+strlen(lbufp)), "DM PF %d ", p_f); + if (cmd == 0) + sprintf((lbufp+strlen(lbufp)), "UI PF %d ", p_f); + if (cmd == 0x40) + sprintf((lbufp+strlen(lbufp)), "DISC PF %d ", p_f); + if (cmd == 0x60) + sprintf((lbufp+strlen(lbufp)), "UA PF %d ", p_f); + if (cmd == 0x84) + sprintf((lbufp+strlen(lbufp)), "FRMR PF %d ", p_f); + if (cmd == 0xac) + sprintf((lbufp+strlen(lbufp)), "XID PF %d ", p_f); + /* information field ??? */ + } + cnt++; + } + break; + } + + /* D channel X.25 */ + + case 16: + if(printit) + sprintf((lbufp+strlen(lbufp)), "Q921: SAP=%d (X.25), %c, TEI=%d, ", sap, cmd?'C':'R', tei); + cnt = n; + goto dump; + + /* Loopback test */ + + case 32: + if(printit) + sprintf((lbufp+strlen(lbufp)), "Q921: SAP=%d (Loopbacktest), %c, TEI=%d, ", sap, cmd?'C':'R', tei); + cnt = n; + goto dump; + + /* SAPI layer 2 management functions */ + + case 63: + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "Q921: SAP=%d (TEI-Management), %c, TEI=%d, ", sap, cmd?'C':'R', tei); + + if (tei != 127) + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "ILLEGAL TEI\n"); + cnt = n; + goto dump; + } + + if (buf [2] != 3 && buf [3] != 0xf) + { + if(printit) + sprintf((lbufp+strlen(lbufp)), "invalid format!\n"); + cnt = n; + goto dump; + } + cnt+= 2; /* UI + MEI */ + + if(printit) + sprintf((lbufp+strlen(lbufp)), "Ri=0x%04hx, ", *(short *)&buf[4]); + cnt += 2; /* Ri */ + + switch (buf[6]) + { + case 1: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdRequest, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 2: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdAssign, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 3: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdDenied, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 4: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdCheckReq, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 5: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdCheckResp, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 6: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdRemove, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + case 7: + if(printit) + sprintf((lbufp+strlen(lbufp)), "IdVerify, Ai=%d", (buf [7] >> 1)); + cnt += 2; + break; + default: + if(printit) + sprintf((lbufp+strlen(lbufp)), "Unknown Msg Type\n"); + cnt = n; + goto dump; + } + break; + } + + /* Illegal SAPI */ + + default: + if(printit) + sprintf((lbufp+strlen(lbufp)), "Q921: ERROR, SAP=%d (Illegal SAPI), %c, TEI=%d\n", sap, cmd?'C':'R', tei); + cnt = n; + goto dump; + } + +dump: + if(printit) + sprintf((lbufp+strlen(lbufp)), "\n"); + + if(raw && printit) + { + int j; + for (i = 0; i < cnt; i += 16) + { + sprintf((pbuf+strlen(pbuf)),"Dump:%.3d ", i); + for (j = 0; j < 16; j++) + if (i + j < cnt) + sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf))," "); + sprintf((pbuf+strlen(pbuf))," "); + for (j = 0; j < 16 && i + j < cnt; j++) + if (isprint(buf[i + j])) + sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf)),"."); + sprintf((pbuf+strlen(pbuf)),"\n"); + } + } + + sprintf((pbuf+strlen(pbuf)),"%s", &locbuf[0]); + + return (cnt); +} + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/q931.c b/usr.sbin/i4b/isdntrace/q931.c new file mode 100644 index 0000000..3cc2a38 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/q931.c @@ -0,0 +1,783 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * q931.c - print Q.931 traces + * --------------------------- + * + * $Id: q931.c,v 1.4 1998/12/05 18:04:19 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:20:31 1998] + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" + +/*---------------------------------------------------------------------------* + * decode Q.931 protocol + *---------------------------------------------------------------------------*/ +void +decode_q931(char *pbuf, int n, int off, unsigned char *buf, int raw) +{ + int codeset = 0; + int codelock = 0; + int oldcodeset = 0; + + int pd; + int len; + int j; + int i; + + if(n <= 0) + return; + + *pbuf = '\0'; + + if(raw) + { + + for (i = 0; i < n; i += 16) + { + sprintf((pbuf+strlen(pbuf)),"Dump:%.3d ", i+off); + for (j = 0; j < 16; j++) + if (i + j < n) + sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf))," "); + sprintf((pbuf+strlen(pbuf))," "); + for (j = 0; j < 16 && i + j < n; j++) + if (isprint(buf[i + j])) + sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf)),"."); + sprintf((pbuf+strlen(pbuf)),"\n"); + } + } + + i = 0; + + sprintf((pbuf+strlen(pbuf)), "Q931: "); + + /* protocol discriminator */ + + pd = buf[i]; + + if(pd >= 0x00 && pd <= 0x07) + sprintf((pbuf+strlen(pbuf)), "pd=User-User (0x%02x), ",pd); + else if(pd == 0x08) + sprintf((pbuf+strlen(pbuf)), "pd=Q.931/I.451, "); + else if(pd >= 0x10 && pd <= 0x3f) + sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x), ",pd); + else if(pd >= 0x40 && pd <= 0x4f) + sprintf((pbuf+strlen(pbuf)), "pd=National Use (0x%02x), ",pd); + else if(pd >= 0x50 && pd <= 0xfe) + sprintf((pbuf+strlen(pbuf)), "pd=Other Layer 3 or X.25 (0x%02x), ",pd); + else + sprintf((pbuf+strlen(pbuf)), "pd=Reserved (0x%02x), ",pd); + + /* call reference */ + + i++; + + len = buf[i] & 0x0f; + + switch(len) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "cr=Dummy, "); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "cr=0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+1] & 0x80) ? "(from destination)" : "(from origination)"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "cr=0x%02x 0x%02x %s, ", (buf[i+1] & 0x7f), (buf[i+2] & 0x7f), (buf[i+1] & 0x80) ? "(org)" : "(dst)"); + break; + } + + i += (len+1); + + /* message type */ + + sprintf((pbuf+strlen(pbuf)), "message="); + + switch(buf[i]) + { + /* escape to nationally specific message type */ + + case 0x00: + sprintf((pbuf+strlen(pbuf)), "ESCAPE: "); + break; + + /* call establishment */ + + case 0x01: + sprintf((pbuf+strlen(pbuf)), "ALERTING: "); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "CALL PROCEEDING: "); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "PROGRESS: "); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "SETUP: "); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "CONNECT: "); + break; + case 0x0d: + sprintf((pbuf+strlen(pbuf)), "SETUP ACKNOWLEDGE: "); + break; + case 0x0f: + sprintf((pbuf+strlen(pbuf)), "CONNECT ACKNOWLEDGE: "); + break; + + /* call information phase */ + + case 0x20: + sprintf((pbuf+strlen(pbuf)), "USER INFORMATION: "); + break; + case 0x21: + sprintf((pbuf+strlen(pbuf)), "SUSPEND REJECT: "); + break; + case 0x22: + sprintf((pbuf+strlen(pbuf)), "RESUME REJECT: "); + break; + case 0x24: + sprintf((pbuf+strlen(pbuf)), "HOLD (Q.932): "); + break; + case 0x25: + sprintf((pbuf+strlen(pbuf)), "SUSPEND: "); + break; + case 0x26: + sprintf((pbuf+strlen(pbuf)), "RESUME: "); + break; + case 0x28: + sprintf((pbuf+strlen(pbuf)), "HOLD ACKNOWLEDGE (Q.932): "); + break; + case 0x2d: + sprintf((pbuf+strlen(pbuf)), "SUSPEND ACKNOWLEDGE: "); + break; + case 0x2e: + sprintf((pbuf+strlen(pbuf)), "RESUME ACKNOWLEDGE: "); + break; + case 0x30: + sprintf((pbuf+strlen(pbuf)), "HOLD REJECT (Q.932): "); + break; + case 0x31: + sprintf((pbuf+strlen(pbuf)), "RETRIEVE (Q.932): "); + break; + case 0x32: + sprintf((pbuf+strlen(pbuf)), "RETRIEVE ACKNOWLEDGE (Q.932): "); + break; + case 0x37: + sprintf((pbuf+strlen(pbuf)), "RETRIEVE REJECT (Q.932): "); + break; + + /* call clearing */ + + case 0x40: + sprintf((pbuf+strlen(pbuf)), "DETACH: "); + break; + case 0x45: + sprintf((pbuf+strlen(pbuf)), "DISCONNECT: "); + break; + case 0x46: + sprintf((pbuf+strlen(pbuf)), "RESTART: "); + break; + case 0x48: + sprintf((pbuf+strlen(pbuf)), "DETACH ACKNOWLEDGE: "); + break; + case 0x4d: + sprintf((pbuf+strlen(pbuf)), "RELEASE: "); + break; + case 0x4e: + sprintf((pbuf+strlen(pbuf)), "RESTART ACKNOWLEDGE: "); + break; + case 0x5a: + sprintf((pbuf+strlen(pbuf)), "RELEASE COMPLETE: "); + break; + + /* misc messages */ + + case 0x60: + sprintf((pbuf+strlen(pbuf)), "SEGMENT: "); + break; + case 0x62: + sprintf((pbuf+strlen(pbuf)), "FACILITY (Q.932): "); + break; + case 0x64: + sprintf((pbuf+strlen(pbuf)), "REGISTER (Q.932): "); + break; + case 0x68: + sprintf((pbuf+strlen(pbuf)), "CANCEL ACKNOWLEDGE: "); + break; + case 0x6a: + sprintf((pbuf+strlen(pbuf)), "FACILITY ACKNOWLEDGE: "); + break; + case 0x6c: + sprintf((pbuf+strlen(pbuf)), "REGISTER ACKNOWLEDGE: "); + break; + case 0x6e: + sprintf((pbuf+strlen(pbuf)), "NOTIFY: "); + break; + case 0x70: + sprintf((pbuf+strlen(pbuf)), "CANCEL REJECT: "); + break; + case 0x72: + sprintf((pbuf+strlen(pbuf)), "FACILITY REJECT: "); + break; + case 0x74: + sprintf((pbuf+strlen(pbuf)), "REGISTER REJECT: "); + break; + case 0x75: + sprintf((pbuf+strlen(pbuf)), "STATUS ENQIRY: "); + break; + case 0x79: + sprintf((pbuf+strlen(pbuf)), "CONGESTION CONTROL: "); + break; + case 0x7b: + sprintf((pbuf+strlen(pbuf)), "INFORMATION: "); + break; + case 0x7d: + sprintf((pbuf+strlen(pbuf)), "STATUS: "); + break; + default: + sprintf((pbuf+strlen(pbuf)), "UNDEFINED, TYPE=0x%02x, ", buf[i]); + break; + } + + /* other information elements */ + + i++; + + for (; i < n;) + { + sprintf((pbuf+strlen(pbuf)), "\n "); + + if(buf[i] & 0x80) + { + /* single octett info element */ + + switch(buf[i] & 0x70) + { + case 0x00: /* reserved */ + sprintf((pbuf+strlen(pbuf)), "[reserved single octett info]"); + break; + + case 0x10: /* shift */ + oldcodeset = codeset; + codeset = buf[i] & 0x07; + if(buf[i] & 0x08) + codelock = 0; + else + codelock = 1; + sprintf((pbuf+strlen(pbuf)), "[shift: codeset=%d lock=%d]", codeset, codelock); + break; + + case 0x20: /* more data */ + if(buf[i] & 0x01) + sprintf((pbuf+strlen(pbuf)), "[sending complete]"); + else + sprintf((pbuf+strlen(pbuf)), "[more data]"); + break; + + case 0x30: /* congestion level */ + sprintf((pbuf+strlen(pbuf)), "[congestion level="); + switch(buf[i] & 0x0f) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "rx-ready]"); + break; + case 0x0f: + sprintf((pbuf+strlen(pbuf)), "rx-not-ready]"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)]", buf[i] & 0x0f); + break; + } + break; + + case 0x50: /* repeat ind */ + sprintf((pbuf+strlen(pbuf)), "[repeat indicator]"); + break; + + default: + sprintf((pbuf+strlen(pbuf)), "[UNKNOWN SINGLE OCTET ELEMENT 0x%02x]", buf[i]); + break; + } + + i++; /* next */ + + } + else + { + /* variable length info element */ + + if(codeset == 0) + { + switch(buf[i]) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "[segmented message: "); + break; + case 0x04: + sprintf((pbuf+strlen(pbuf)), "[bearer capability: "); + i += p_q931bc(pbuf, &buf[i]); + goto next; + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "[cause: "); + i += p_q931cause(pbuf, &buf[i]); + goto next; + break; + case 0x0c: + sprintf((pbuf+strlen(pbuf)), "[connected address (old): "); + break; + case 0x0d: + sprintf((pbuf+strlen(pbuf)), "[extended facility (Q.932: )"); + break; + case 0x10: + sprintf((pbuf+strlen(pbuf)), "[call identity: "); + break; + case 0x14: + sprintf((pbuf+strlen(pbuf)), "[call state: "); + i++; + len = buf[i]; + i++; + sprintf((pbuf+strlen(pbuf)), "Std="); + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "CCITT"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "ISO/IEC"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "National"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Special"); + break; + } + sprintf((pbuf+strlen(pbuf)), ", State="); + + switch((buf[i] & 0x3f)) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "Null"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "Call initiated"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "Overlap sending"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Outgoing call proceeding"); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), "Call delivered"); + break; + case 6: + sprintf((pbuf+strlen(pbuf)), "Call present"); + break; + case 7: + sprintf((pbuf+strlen(pbuf)), "Call received"); + break; + case 8: + sprintf((pbuf+strlen(pbuf)), "Connect request"); + break; + case 9: + sprintf((pbuf+strlen(pbuf)), "Incoming call proceeding"); + break; + case 10: + sprintf((pbuf+strlen(pbuf)), "Active"); + break; + case 11: + sprintf((pbuf+strlen(pbuf)), "Disconnect request"); + break; + case 12: + sprintf((pbuf+strlen(pbuf)), "Disconnect indication"); + break; + case 15: + sprintf((pbuf+strlen(pbuf)), "Suspend request"); + break; + case 17: + sprintf((pbuf+strlen(pbuf)), "Resume request"); + break; + case 19: + sprintf((pbuf+strlen(pbuf)), "Release request"); + break; + case 22: + sprintf((pbuf+strlen(pbuf)), "Call abort"); + break; + case 25: + sprintf((pbuf+strlen(pbuf)), "Overlap receiving"); + break; + case 0x3d: + sprintf((pbuf+strlen(pbuf)), "Restart request"); + break; + case 0x3e: + sprintf((pbuf+strlen(pbuf)), "Restart"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved"); + break; + } + sprintf((pbuf+strlen(pbuf)), "]"); + i++; + goto next; + break; + case 0x18: + sprintf((pbuf+strlen(pbuf)), "[channel id: channel="); + i++; + len = buf[i]; + i++; + switch(buf[i] & 0x03) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "no channel"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "B-1"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "B-2"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "any channel"); + break; + } + if(buf[i] & 0x08) + sprintf((pbuf+strlen(pbuf)), " (exclusive)]"); + else + sprintf((pbuf+strlen(pbuf)), " (preferred)]"); + i++; + goto next; + break; + case 0x19: + sprintf((pbuf+strlen(pbuf)), "[data link connection id (Q.933): "); + break; + case 0x1c: + i += q932_facility(pbuf, &buf[i]); + goto next; + break; + case 0x1e: + sprintf((pbuf+strlen(pbuf)), "[progress ind: "); + i++; + len = buf[i]; + i++; + sprintf((pbuf+strlen(pbuf)), "Std="); + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "CCITT"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "ISO/IEC"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "National"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Local"); + break; + } + sprintf((pbuf+strlen(pbuf)), ", Loc="); + + switch((buf[i] & 0x0f)) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "User"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "Private network serving local user"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "Public network serving local user"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Transit network"); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), "Public network serving remote user"); + break; + case 5: + sprintf((pbuf+strlen(pbuf)), "Private network serving remote user"); + break; + case 6: + sprintf((pbuf+strlen(pbuf)), "Network beyond interworking point"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved"); + break; + } + + i++; + + sprintf((pbuf+strlen(pbuf)), "\n Description: "); + + switch((buf[i] & 0x7f)) + { + case 1: + sprintf((pbuf+strlen(pbuf)), "Call is not end-to-end ISDN"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "Destination address is non-ISDN"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Origination address is non-ISDN"); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), "Call has returned to the ISDN"); + break; + case 5: + sprintf((pbuf+strlen(pbuf)), "Interworking occured, Service change"); + break; + case 8: + sprintf((pbuf+strlen(pbuf)), "In-band info or appropriate pattern now available"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "ERROR: undefined/reserved"); + break; + } + sprintf((pbuf+strlen(pbuf)), "]"); + i++; + goto next; + break; + case 0x20: + sprintf((pbuf+strlen(pbuf)), "[network specific facilities: "); + break; + case 0x24: + sprintf((pbuf+strlen(pbuf)), "[terminal capabilities: "); + break; + case 0x27: + sprintf((pbuf+strlen(pbuf)), "[notification ind: "); + break; + case 0x28: + sprintf((pbuf+strlen(pbuf)), "[display: "); + i++; + len = buf[i]; + i++; + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]); + } + sprintf((pbuf+strlen(pbuf)),"]"); + i += j; + goto next; + break; + case 0x29: + sprintf((pbuf+strlen(pbuf)), "[date/time: "); + i++; + len = buf[i]; + i++; + j = 0; + sprintf((pbuf+strlen(pbuf)),"%.2d.%.2d.%.2d", + buf[i+2], buf[i+1], buf[i]); + j+=3; + if(j < len) + { + sprintf((pbuf+strlen(pbuf))," %.2d", buf[i+3]); + j++; + } + if(j < len) + { + sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+4]); + j++; + } + if(j < len) + { + sprintf((pbuf+strlen(pbuf)),":%.2d", buf[i+5]); + j++; + } + sprintf((pbuf+strlen(pbuf)),"]"); + i += len; + goto next; + break; + case 0x2c: + sprintf((pbuf+strlen(pbuf)), "[keypad: "); + break; + case 0x30: + sprintf((pbuf+strlen(pbuf)), "[keypad echo: "); + break; + case 0x32: + sprintf((pbuf+strlen(pbuf)), "[information req (Q.932): "); + break; + case 0x34: + sprintf((pbuf+strlen(pbuf)), "[signal: "); + break; + case 0x36: + sprintf((pbuf+strlen(pbuf)), "[switchhook: "); + break; + case 0x38: + sprintf((pbuf+strlen(pbuf)), "[feature activation (Q.932): "); + break; + case 0x39: + sprintf((pbuf+strlen(pbuf)), "[feature ind (Q.932): "); + break; + case 0x3a: + sprintf((pbuf+strlen(pbuf)), "[service profile id (Q.932): "); + break; + case 0x3b: + sprintf((pbuf+strlen(pbuf)), "[endpoint id (Q.932): "); + break; + case 0x40: + sprintf((pbuf+strlen(pbuf)), "[information rate: "); + break; + case 0x41: + sprintf((pbuf+strlen(pbuf)), "[precedence level (Q.955): "); + break; + case 0x42: + sprintf((pbuf+strlen(pbuf)), "[end-to-end transit delay: "); + break; + case 0x43: + sprintf((pbuf+strlen(pbuf)), "[transit delay detection and indication: "); + break; + case 0x44: + sprintf((pbuf+strlen(pbuf)), "[packet layer binary parameters: "); + break; + case 0x45: + sprintf((pbuf+strlen(pbuf)), "[packet layer window size: "); + break; + case 0x46: + sprintf((pbuf+strlen(pbuf)), "[packet size: "); + break; + case 0x47: + sprintf((pbuf+strlen(pbuf)), "[closed user group: "); + break; + case 0x48: + sprintf((pbuf+strlen(pbuf)), "[link layer core parameters (Q.933): "); + break; + case 0x49: + sprintf((pbuf+strlen(pbuf)), "[link layer protocol parameters (Q.933): "); + break; + case 0x4a: + sprintf((pbuf+strlen(pbuf)), "[reverse charging information: "); + break; + case 0x4c: + sprintf((pbuf+strlen(pbuf)), "[connected number (Q.951): "); + i += p_q931address(pbuf, &buf[i]); + goto next; + break; + + break; + case 0x4d: + sprintf((pbuf+strlen(pbuf)), "[connected subaddress (Q.951): "); + break; + case 0x50: + sprintf((pbuf+strlen(pbuf)), "[X.213 priority (Q.933): "); + break; + case 0x51: + sprintf((pbuf+strlen(pbuf)), "[report type (Q.933): "); + break; + case 0x53: + sprintf((pbuf+strlen(pbuf)), "[link integrity verification (Q.933): "); + break; + case 0x57: + sprintf((pbuf+strlen(pbuf)), "[PVC status (Q.933): "); + break; + case 0x6c: + sprintf((pbuf+strlen(pbuf)), "[calling party number: "); + i += p_q931address(pbuf, &buf[i]); + goto next; + break; + case 0x6d: + sprintf((pbuf+strlen(pbuf)), "[calling party subaddress: "); + break; + case 0x70: + sprintf((pbuf+strlen(pbuf)), "[called party number: "); + i += p_q931address(pbuf, &buf[i]); + goto next; + break; + case 0x71: + sprintf((pbuf+strlen(pbuf)), "[called party subaddress: "); + break; + case 0x74: + sprintf((pbuf+strlen(pbuf)), "[redirecting number: "); + break; + case 0x76: + sprintf((pbuf+strlen(pbuf)), "[redirection number: "); + break; + case 0x78: + sprintf((pbuf+strlen(pbuf)), "[transit network selection: "); + break; + case 0x79: + sprintf((pbuf+strlen(pbuf)), "[restart indicator: "); + break; + case 0x7c: + sprintf((pbuf+strlen(pbuf)), "[low layer compatibility: "); + break; + case 0x7d: + sprintf((pbuf+strlen(pbuf)), "[high layer compatibility:"); + i += p_q931high_compat(pbuf, &buf[i]); + goto next; + break; + case 0x7e: + sprintf((pbuf+strlen(pbuf)), "[user-user: "); + break; + case 0x7f: + sprintf((pbuf+strlen(pbuf)), "[escape for extension: "); + break; + default: + sprintf((pbuf+strlen(pbuf)), "[UNKNOWN INFO-ELEMENT-ID=0x%02x: ", buf[i]); + break; + } + } + else + { + sprintf((pbuf+strlen(pbuf)), "[UNKNOWN CODESET=%d, IE=0x%02x: ", codeset, buf[i]); + } + + i++; /* index -> length */ + + len = buf[i]; + + sprintf((pbuf+strlen(pbuf)), "LEN=0x%02x, DATA=", len); + + i++; /* index -> 1st param */ + + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"0x%02x ", buf[j+i]); + } + + sprintf((pbuf+strlen(pbuf)),"]"); + + i += len; + +next: + + if(!codelock && (codeset != oldcodeset)) + codeset = oldcodeset; + } + } + sprintf((pbuf+strlen(pbuf)),"\n"); +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdntrace/q931_util.c b/usr.sbin/i4b/isdntrace/q931_util.c new file mode 100644 index 0000000..1b2ab09 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/q931_util.c @@ -0,0 +1,697 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * q931_util.c - utility functions to print Q.931 traces + * ----------------------------------------------------- + * + * $Id: q931_util.c,v 1.4 1998/12/05 18:04:21 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:20:43 1998] + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" + +/*---------------------------------------------------------------------------* + * decode and print the cause + *---------------------------------------------------------------------------*/ +int +p_q931cause(char *pbuf, unsigned char *buf) +{ + int j; + int len; + int i = 0; + int ls; + int r = 0; + int rflag = 0; + + i++; /* index -> length */ + + len = buf[i]; + + i++; /* coding/location */ + len--; + + ls = buf[i]; + + i++; + len--; + + if(!(buf[i-1] & 0x80)) + { + r = buf[i]; + rflag = 1; + i++; + len--; + } + + sprintf((pbuf+strlen(pbuf)), "%s ", print_cause_q850(buf[i] & 0x7f)); + + sprintf((pbuf+strlen(pbuf)), "\n (location="); + + switch(ls & 0x0f) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "user"); + break; + case 0x01: + sprintf((pbuf+strlen(pbuf)), "private network serving local user"); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "public network serving local user"); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "transit network"); + break; + case 0x04: + sprintf((pbuf+strlen(pbuf)), "public network serving remote user"); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "private network serving remote user"); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "international network"); + break; + case 0x0a: + sprintf((pbuf+strlen(pbuf)), "network beyond interworking point"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", ls & 0x0f); + break; + } + + sprintf((pbuf+strlen(pbuf)), ", std="); + + switch((ls & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "CCITT"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "ISO/IEC"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "National"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "Local"); + break; + } + + if(rflag) + { + sprintf((pbuf+strlen(pbuf)), ", rec="); + + switch(r & 0x7f) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "Q.931"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "X.21"); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), "X.25"); + break; + case 5: + sprintf((pbuf+strlen(pbuf)), "Q.1031/Q.1051"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "Reserved"); + break; + } + } + + sprintf((pbuf+strlen(pbuf)),")"); + + i++; + len--; + + for(j = 0; j < len; j++) + sprintf((pbuf+strlen(pbuf))," 0x%02x", buf[j+i]); + + sprintf((pbuf+strlen(pbuf)),"]"); + + i += (len+1); + + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the bearer capability + *---------------------------------------------------------------------------*/ +int +p_q931bc(char *pbuf, unsigned char *buf) +{ + int len; + int i = 0; + int mr = 0; + + i++; /* index -> length */ + + len = buf[i]; + + i++; + + sprintf((pbuf+strlen(pbuf)), "\n cap="); + + switch(buf[i] & 0x1f) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "speech"); + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "unrestricted digital information"); + break; + case 0x09: + sprintf((pbuf+strlen(pbuf)), "restricted digital information"); + break; + case 0x10: + sprintf((pbuf+strlen(pbuf)), "3.1 kHz audio"); + break; + case 0x11: + sprintf((pbuf+strlen(pbuf)), "unrestricted digital information with tones"); + break; + case 0x18: + sprintf((pbuf+strlen(pbuf)), "video"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + + sprintf((pbuf+strlen(pbuf)), "\n std="); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "CCITT"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "ISO/IEC"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "National"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "NSI Std"); + break; + } + + i++; + len--; + + sprintf((pbuf+strlen(pbuf)), "\n rate="); + + switch(buf[i] & 0x1f) + { + case 0x00: + sprintf((pbuf+strlen(pbuf)), "packet mode"); + break; + case 0x10: + sprintf((pbuf+strlen(pbuf)), "64 kbit/s"); + break; + case 0x11: + sprintf((pbuf+strlen(pbuf)), "2 x 64 kbit/s"); + break; + case 0x13: + sprintf((pbuf+strlen(pbuf)), "384 kbit/s"); + break; + case 0x15: + sprintf((pbuf+strlen(pbuf)), "1536 kbit/s"); + break; + case 0x17: + sprintf((pbuf+strlen(pbuf)), "1920 kbit/s"); + break; + case 0x18: + sprintf((pbuf+strlen(pbuf)), "Multirate"); + mr = 1; + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + + sprintf((pbuf+strlen(pbuf)), "\n mode="); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "circuit"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "packet"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", ((buf[i] & 0x60) >> 5)); + break; + } + + i++; + len--; + + if(!len) + goto exit; + + if(mr) + { + sprintf((pbuf+strlen(pbuf)), "\n rate multiplier=%d", buf[i] & 0x7f); + i++; + len--; + } + + if(!len) + goto exit; + + sprintf((pbuf+strlen(pbuf)), "\n layer1="); + + switch(buf[i] & 0x1f) + { + case 0x01: + sprintf((pbuf+strlen(pbuf)), "V.110"); + break; + case 0x02: + sprintf((pbuf+strlen(pbuf)), "G.711 u-law"); + break; + case 0x03: + sprintf((pbuf+strlen(pbuf)), "G.711 A-law"); + break; + case 0x04: + sprintf((pbuf+strlen(pbuf)), "G.721"); + break; + case 0x05: + sprintf((pbuf+strlen(pbuf)), "H.221/H.242"); + break; + case 0x07: + sprintf((pbuf+strlen(pbuf)), "Non-Std"); + break; + case 0x08: + sprintf((pbuf+strlen(pbuf)), "V.120"); + break; + case 0x09: + sprintf((pbuf+strlen(pbuf)), "X.31"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "reserved (0x%02x)", buf[i] & 0x0f); + break; + } + i++; + len--; + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n user rate=0x%02x ", buf[i] & 0x1f); + + if(buf[i] & 0x40) + sprintf((pbuf+strlen(pbuf)), "(async,"); + else + sprintf((pbuf+strlen(pbuf)), "(sync,"); + + if(buf[i] & 0x20) + sprintf((pbuf+strlen(pbuf)), "in-band neg. possible)"); + else + sprintf((pbuf+strlen(pbuf)), "in-band neg not possible)"); + + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n clk/flow=0x%02x", buf[i] & 0x1f); + + sprintf((pbuf+strlen(pbuf)), "\n intermediate rate="); + + switch((buf[i] & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "not used"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "8 kbit/s"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "16 kbit/s"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "32 kbit/s"); + break; + } + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n hdr/mfrm/etc.=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n stop/data/parity=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + if(!(buf[i-1] & 0x80)) + { + sprintf((pbuf+strlen(pbuf)), "\n modemtype=0x%02x", buf[i]); + i++; + len--; + } + + if(!len) + goto exit; + + switch(buf[i] & 0x7f) + { + case 0x42: + sprintf((pbuf+strlen(pbuf)), "\n layer2=Q.921/I.441"); + break; + case 0x46: + sprintf((pbuf+strlen(pbuf)), "\n layer2=X.25 link"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "\n layer2=0x%02x",(buf[i] & 0x7f)); + break; + } + i++; + len--; + + if(!len) + goto exit; + + switch(buf[i] & 0x7f) + { + case 0x62: + sprintf((pbuf+strlen(pbuf)), "\n layer3=Q.921/I.441"); + break; + case 0x66: + sprintf((pbuf+strlen(pbuf)), "\n layer3=X.25 packet"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "\n layer3=0x%02x",(buf[i] & 0x7f)); + break; + } + i++; + len--; + +exit: + sprintf((pbuf+strlen(pbuf)), "]"); + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print the ISDN (telephone) number + *---------------------------------------------------------------------------*/ +int +p_q931address(char *pbuf, unsigned char *buf) +{ + int j; + int len; + int i = 0; + int tp; + int ind = 0; + int indflag = 0; + + i++; /* index -> length */ + len = buf[i]; + + i++; /* index -> type/plan */ + tp = buf[i]; + + i++; + len--; + + if(!(tp & 0x80)) + { + ind = buf[i]; + indflag = 1; + i++; + len--; + } + + for(j = 0; j < len; j++) + { + sprintf((pbuf+strlen(pbuf)),"%c", buf[j+i]); + } + + switch((tp & 0x70) >> 4) + { + case 0: + sprintf((pbuf+strlen(pbuf)), " (type=unknown, "); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), " (type=international, "); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), " (type=national, "); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), " (type=network specific, "); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), " (type=subscriber, "); + break; + case 6: + sprintf((pbuf+strlen(pbuf)), " (type=abbreviated, "); + break; + default: + sprintf((pbuf+strlen(pbuf)), " (type=reserved (%d), ", ((tp & 0x70) >> 4)); + break; + } + + switch(tp & 0x0f) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "plan=unknown"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "plan=ISDN"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "plan=Data"); + break; + case 4: + sprintf((pbuf+strlen(pbuf)), "plan=Telex"); + break; + case 8: + sprintf((pbuf+strlen(pbuf)), "plan=National"); + break; + case 9: + sprintf((pbuf+strlen(pbuf)), "plan=private"); + break; + default: + sprintf((pbuf+strlen(pbuf)), "plan=reserved (%d)", (tp & 0x0f)); + break; + } + + if(indflag) + { + sprintf((pbuf+strlen(pbuf)), ",\n "); + switch((ind & 0x60) >> 5) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "presentation allowed, "); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "presentation restricted, "); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "number not available, "); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "reserved, "); + break; + } + + switch(ind & 0x03) + { + case 0: + sprintf((pbuf+strlen(pbuf)), "screening user provided: not screened"); + break; + case 1: + sprintf((pbuf+strlen(pbuf)), "screening user provided: verified & passed"); + break; + case 2: + sprintf((pbuf+strlen(pbuf)), "screening user provided: verified & failed"); + break; + case 3: + sprintf((pbuf+strlen(pbuf)), "screening network provided"); + break; + } + } + + sprintf((pbuf+strlen(pbuf)),")]"); + + i += j; + + return(i); +} + +/*---------------------------------------------------------------------------* + * decode and print HL comatibility + *---------------------------------------------------------------------------*/ +int +p_q931high_compat(char *pbuf, unsigned char *buf) +{ + int len = buf[1]; + + sprintf(pbuf+strlen(pbuf), " standard="); + + switch ((buf[2] >> 5) & 0x03) + { + case 0: sprintf(pbuf+strlen(pbuf), "CCITT"); + break; + case 1: sprintf(pbuf+strlen(pbuf), "unknown international standard"); + break; + case 2: sprintf(pbuf+strlen(pbuf), "unknown national standard"); + break; + case 3: sprintf(pbuf+strlen(pbuf), "local network standard"); + } + + len--; + + sprintf(pbuf+strlen(pbuf), ", characteristics="); + + switch (buf[3] & 0x7f) + { + case 0x01: + sprintf(pbuf+strlen(pbuf), "Telephony"); + break; + case 0x04: + sprintf(pbuf+strlen(pbuf), "Fax Group 2/3"); + break; + case 0x21: + sprintf(pbuf+strlen(pbuf), "Fax Group 4 Class I (F.184)"); + break; + case 0x24: + sprintf(pbuf+strlen(pbuf), "Teletex basic/mixed (F.230) or Fax Group 4 Class II/III (F.184)"); + break; + case 0x28: + sprintf(pbuf+strlen(pbuf), "Teletex basic/processable (F.220)"); + break; + case 0x31: + sprintf(pbuf+strlen(pbuf), "Teletex basic mode (F.200)"); + break; + case 0x32: + sprintf(pbuf+strlen(pbuf), "Videotex (F.300 and T.101)"); + break; + case 0x35: + sprintf(pbuf+strlen(pbuf), "Telex (F.60)"); + break; + case 0x38: + sprintf(pbuf+strlen(pbuf), "MHS (X.400 series)"); + break; + case 0x41: + sprintf(pbuf+strlen(pbuf), "OSI application (X.200 series)"); + break; + case 0x5e: + sprintf(pbuf+strlen(pbuf), "Maintenance"); + break; + case 0x5f: + sprintf(pbuf+strlen(pbuf), "Management"); + break; + case 0x7f: + sprintf(pbuf+strlen(pbuf), "reserved"); + break; + default: + sprintf(pbuf+strlen(pbuf), "UNKNOWN (0x%02x)", buf[3]); + break; + } + + len--; + + if (!len) + { + sprintf(pbuf+strlen(pbuf), "]"); + return 4; + } + + sprintf(pbuf+strlen(pbuf), " of "); + + switch (buf[4] & 0x7f) + { + case 0x01: + sprintf(pbuf+strlen(pbuf), "Telephony"); + break; + case 0x04: + sprintf(pbuf+strlen(pbuf), "Fax Group 2/3"); + break; + case 0x21: + sprintf(pbuf+strlen(pbuf), "Fax Group 4 Class I (F.184)"); + break; + case 0x24: + sprintf(pbuf+strlen(pbuf), "Teletex basic/mixed (F.230) or Fax Group 4 Class II/III (F.184)"); + break; + case 0x28: + sprintf(pbuf+strlen(pbuf), "Teletex basic/processable (F.220)"); + break; + case 0x31: + sprintf(pbuf+strlen(pbuf), "Teletex basic mode (F.200)"); + break; + case 0x32: + sprintf(pbuf+strlen(pbuf), "Videotex (F.300 and T.101)"); + break; + case 0x35: + sprintf(pbuf+strlen(pbuf), "Telex (F.60)"); + break; + case 0x38: + sprintf(pbuf+strlen(pbuf), "MHS (X.400 series)"); + break; + case 0x41: + sprintf(pbuf+strlen(pbuf), "OSI application (X.200 series)"); + break; + case 0x7f: + sprintf(pbuf+strlen(pbuf), "reserved"); + break; + default: + sprintf(pbuf+strlen(pbuf), "UNKNOWN (0x%02x)", buf[3]); + break; + } + sprintf(pbuf+strlen(pbuf), "]"); + return 5; +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdntrace/q932_fac.c b/usr.sbin/i4b/isdntrace/q932_fac.c new file mode 100644 index 0000000..ba3f59d --- /dev/null +++ b/usr.sbin/i4b/isdntrace/q932_fac.c @@ -0,0 +1,926 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * q932_fac.c - decode Q.932 facilities + * ------------------------------------ + * + * $Id: q932_fac.c,v 1.4 1998/12/05 18:04:22 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:20:58 1998] + * + *--------------------------------------------------------------------------- + * + * - Q.932 (03/93) Generic Procedures for the Control of + * ISDN Supplementaty Services + * - Q.950 (03/93) Supplementary Services Protocols, Structure and + * General Principles + * - ETS 300 179 (10/92) Advice Of Charge: charging information during + * the call (AOC-D) supplementary service Service description + * - ETS 300 180 (10/92) Advice Of Charge: charging information at the + * end of call (AOC-E) supplementary service Service description + * - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service + * Functional capabilities and information flows + * - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service + * Digital Subscriber Signalling System No. one (DSS1) protocol + * - X.208 Specification of Abstract Syntax Notation One (ASN.1) + * - X.209 Specification of Basic Encoding Rules for + * Abstract Syntax Notation One (ASN.1) + * - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag + * 1992, 3rd Edition (ISBN 3-89238-062-7) (german !) + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" +#include "q932_fac.h" + +static int do_component(int length, char *pbuf); +static char *uni_str(int code); +static char *opval_str(int val); +static char *bid_str(int val); +static void next_state(char *pbuf, int class, int form, int code, int val); + +static int byte_len; +static unsigned char *byte_buf; +static int state; + +/*---------------------------------------------------------------------------* + * decode Q.931/Q.932 facility info element + *---------------------------------------------------------------------------*/ +int +q932_facility(char *pbuf, unsigned char *buf) +{ + int len; + + sprintf((pbuf+strlen(pbuf)), "[facility (Q.932): "); + + buf++; /* length */ + + len = *buf; + + buf++; /* protocol profile */ + + sprintf((pbuf+strlen(pbuf)), "Protocol="); + + switch(*buf & 0x1f) + { + case FAC_PROTO_ROP: + sprintf((pbuf+strlen(pbuf)), "Remote Operations Protocol\n"); + break; + + case FAC_PROTO_CMIP: + sprintf((pbuf+strlen(pbuf)), "CMIP Protocol (Q.941), UNSUPPORTED!\n"); + return(len+2); + break; + + case FAC_PROTO_ACSE: + sprintf((pbuf+strlen(pbuf)), "ACSE Protocol (X.217/X.227), UNSUPPORTED!\n"); + return(len+2); + break; + + default: + sprintf((pbuf+strlen(pbuf)), "Unknown Protocol (val = 0x%x), UNSUPPORTED!\n", *buf & 0x1f); + return(len+2); + break; + } + + /* next byte */ + + buf++; + len--; + + /* initialize variables for do_component */ + + byte_len = 0; + byte_buf = buf; + state = ST_EXP_COMP_TYP; + + /* decode facility */ + + do_component(len, pbuf); + + sprintf((pbuf+(strlen(pbuf)-1)), "]"); /* XXX replace last newline */ + + return(len+3); +} + +/*---------------------------------------------------------------------------* + * handle a component recursively + *---------------------------------------------------------------------------*/ +static int +do_component(int length, char *pbuf) +{ + int comp_tag_class; /* component tag class */ + int comp_tag_form; /* component form: constructor or primitive */ + int comp_tag_code; /* component code depending on class */ + int comp_length = 0; /* component length */ + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "ENTER - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + +again: + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "AGAIN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + + /*----------------------------------------*/ + /* first component element: component tag */ + /*----------------------------------------*/ + + /* tag class bits */ + + sprintf((pbuf+strlen(pbuf)), "\t0x%02x Tag: ", *byte_buf); + + comp_tag_class = (*byte_buf & 0xc0) >> 6; + + switch(comp_tag_class) + { + case FAC_TAGCLASS_UNI: + sprintf((pbuf+strlen(pbuf)), "Universal"); + break; + case FAC_TAGCLASS_APW: + sprintf((pbuf+strlen(pbuf)), "Applic-wide"); + break; + case FAC_TAGCLASS_COS: + sprintf((pbuf+strlen(pbuf)), "Context-spec"); + break; + case FAC_TAGCLASS_PRU: + sprintf((pbuf+strlen(pbuf)), "Private"); + break; + } + + /* tag form bit */ + + comp_tag_form = (*byte_buf & 0x20) > 5; + + sprintf((pbuf+strlen(pbuf)), ", "); + + if(comp_tag_form == FAC_TAGFORM_CON) + { + sprintf((pbuf+strlen(pbuf)), "Constructor"); + } + else + { + sprintf((pbuf+strlen(pbuf)), "Primitive"); + } + + /* tag code bits */ + + comp_tag_code = *byte_buf & 0x1f; + + sprintf((pbuf+strlen(pbuf)), ", "); + + if(comp_tag_code == 0x1f) + { + comp_tag_code = 0; + + byte_buf++; + byte_len++; + + while(*byte_buf & 0x80) + { + comp_tag_code += (*byte_buf & 0x7f); + byte_buf++; + byte_len++; + } + comp_tag_code += (*byte_buf & 0x7f); + sprintf((pbuf+strlen(pbuf)), "%d (ext)\n", comp_tag_code); + } + else + { + comp_tag_code = (*byte_buf & 0x1f); + + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + sprintf((pbuf+strlen(pbuf)), "%s (%d)\n", uni_str(comp_tag_code), comp_tag_code); + } + else + { + sprintf((pbuf+strlen(pbuf)), "code = %d\n", comp_tag_code); + } + } + + byte_buf++; + byte_len++; + + /*--------------------------------------------*/ + /* second component element: component length */ + /*--------------------------------------------*/ + + sprintf((pbuf+strlen(pbuf)), "\t0x%02x Len: ", *byte_buf); + + comp_length = 0; + + if(*byte_buf & 0x80) + { + int i = *byte_buf & 0x7f; + + byte_len += i; + + for(;i > 0;i++) + { + byte_buf++; + comp_length += (*byte_buf * (i*256)); + } + sprintf((pbuf+strlen(pbuf)), "%d (long form)\n", comp_length); + } + else + { + comp_length = *byte_buf & 0x7f; + sprintf((pbuf+strlen(pbuf)), "%d (short form)\n", comp_length); + } + + next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, -1); + + byte_len++; + byte_buf++; + + if(comp_length) + { + + /*---------------------------------------------*/ + /* third component element: component contents */ + /*---------------------------------------------*/ + + if(comp_tag_form) /* == constructor */ + { + do_component(comp_length, pbuf); + } + else + { + int val = 0; + if(comp_tag_class == FAC_TAGCLASS_UNI) + { + switch(comp_tag_code) + { + case FAC_CODEUNI_INT: + case FAC_CODEUNI_ENUM: + case FAC_CODEUNI_BOOL: + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x ", *byte_buf); + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + sprintf((pbuf+strlen(pbuf)), "Val: %d\n", val); + } + break; + default: + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x = %d", *byte_buf, *byte_buf); + if(isprint(*byte_buf)) + sprintf((pbuf+strlen(pbuf)), " = '%c'", *byte_buf); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + } + break; + } + } + + else /* comp_tag_class != FAC_TAGCLASS_UNI */ + { + if(comp_length) + { + int i; + + sprintf((pbuf+strlen(pbuf)), "\t"); + + for(i = comp_length-1; i >= 0; i--) + { + sprintf((pbuf+strlen(pbuf)), "0x%02x", *byte_buf); + val += (*byte_buf + (i*255)); + byte_buf++; + byte_len++; + if(i) + sprintf((pbuf+strlen(pbuf)), "\n\t"); + } + sprintf((pbuf+strlen(pbuf)), "\n"); + } + } + next_state(pbuf, comp_tag_class, comp_tag_form, comp_tag_code, val); + } + } + +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "PREGOTO - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + if(byte_len < length) + goto again; +#ifdef FAC_DEBUG + sprintf((pbuf+strlen(pbuf)), "RETURN - comp_length = %d, byte_len = %d, length =%d\n", comp_length, byte_len, length); +#endif + return(byte_len); +} + +/*---------------------------------------------------------------------------* + * print universal id type + *---------------------------------------------------------------------------*/ +static char *uni_str(int code) +{ + static char *tbl[] = { + "BOOLEAN", + "INTEGER", + "BIT STRING", + "OCTET STRING", + "NULL", + "OBJECT IDENTIFIER", + "OBJECT DESCRIPTOR", + "EXTERNAL", + "REAL", + "ENUMERATED", + "RESERVED11", + "RESERVED12", + "RESERVED13", + "RESERVED14", + "RESERVED15", + "SEQUENCE", + "SET", + "NUMERIC STRING", + "PRINTABLE STRING", + "TELETEX STRING", + "ISO646 STRING", + "IA5 STRING", + "GRAPHIC STRING", + "GENERAL STRING" + }; + + if(code >= 1 && code <= FAC_CODEUNI_GNSTR) + return(tbl[code-1]); + else + return("ERROR, Value out of Range!"); +} + +/*---------------------------------------------------------------------------* + * print operation value + *---------------------------------------------------------------------------*/ +static char *opval_str(int val) +{ + static char buffer[80]; + char *r; + + switch(val) + { + case FAC_OPVAL_UUS: + r = "uUs"; + break; + case FAC_OPVAL_CUG: + r = "cUGCall"; + break; + case FAC_OPVAL_MCID: + r = "mCIDRequest"; + break; + case FAC_OPVAL_BTPY: + r = "beginTPY"; + break; + case FAC_OPVAL_ETPY: + r = "endTPY"; + break; + case FAC_OPVAL_ECT: + r = "eCTRequest"; + break; + case FAC_OPVAL_DIV_ACT: + r = "activationDiversion"; + break; + case FAC_OPVAL_DIV_DEACT: + r = "deactivationDiversion"; + break; + case FAC_OPVAL_DIV_ACTSN: + r = "activationStatusNotificationDiv"; + break; + case FAC_OPVAL_DIV_DEACTSN: + r = "deactivationStatusNotificationDiv"; + break; + case FAC_OPVAL_DIV_INTER: + r = "interrogationDiversion"; + break; + case FAC_OPVAL_DIV_INFO: + r = "diversionInformation"; + break; + case FAC_OPVAL_DIV_CALLDEF: + r = "callDeflection"; + break; + case FAC_OPVAL_DIV_CALLRER: + r = "callRerouting"; + break; + case FAC_OPVAL_DIV_LINF2: + r = "divertingLegInformation2"; + break; + case FAC_OPVAL_DIV_INVS: + r = "invokeStatus"; + break; + case FAC_OPVAL_DIV_INTER1: + r = "interrogationDiversion1"; + break; + case FAC_OPVAL_DIV_LINF1: + r = "divertingLegInformation1"; + break; + case FAC_OPVAL_DIV_LINF3: + r = "divertingLegInformation3"; + break; + case FAC_OPVAL_ER_CRCO: + r = "explicitReservationCreationControl"; + break; + case FAC_OPVAL_ER_MGMT: + r = "explicitReservationManagement"; + break; + case FAC_OPVAL_ER_CANC: + r = "explicitReservationCancel"; + break; + case FAC_OPVAL_MLPP_QUERY: + r = "mLPP lfb Query"; + break; + case FAC_OPVAL_MLPP_CALLR: + r = "mLPP Call Request"; + break; + case FAC_OPVAL_MLPP_CALLP: + r = "mLPP Call Preemption"; + break; + case FAC_OPVAL_AOC_REQ: + r = "chargingRequest"; + break; + case FAC_OPVAL_AOC_S_CUR: + r = "aOCSCurrency"; + break; + case FAC_OPVAL_AOC_S_SPC: + r = "aOCSSpecialArrangement"; + break; + case FAC_OPVAL_AOC_D_CUR: + r = "aOCDCurrency"; + break; + case FAC_OPVAL_AOC_D_UNIT: + r = "aOCDChargingUnit"; + break; + case FAC_OPVAL_AOC_E_CUR: + r = "aOCECurrency"; + break; + case FAC_OPVAL_AOC_E_UNIT: + r = "aOCEChargingUnit"; + break; + case FAC_OPVAL_AOC_IDOFCRG: + r = "identificationOfCharge"; + break; + case FAC_OPVAL_CONF_BEG: + r = "beginConf"; + break; + case FAC_OPVAL_CONF_ADD: + r = "addConf"; + break; + case FAC_OPVAL_CONF_SPLIT: + r = "splitConf"; + break; + case FAC_OPVAL_CONF_DROP: + r = "dropConf"; + break; + case FAC_OPVAL_CONF_ISOLATE: + r = "isolateConf"; + break; + case FAC_OPVAL_CONF_REATT: + r = "reattachConf"; + break; + case FAC_OPVAL_CONF_PDISC: + r = "partyDISC"; + break; + case FAC_OPVAL_CONF_FCONF: + r = "floatConf"; + break; + case FAC_OPVAL_CONF_END: + r = "endConf"; + break; + case FAC_OPVAL_CONF_IDCFE: + r = "indentifyConferee"; + break; + case FAC_OPVAL_REVC_REQ: + r = "requestREV"; + break; + default: + sprintf(buffer, "unknown operation value %d!", val); + r = buffer; + } + return(r); +} + +/*---------------------------------------------------------------------------* + * billing id string + *---------------------------------------------------------------------------*/ +static char *bid_str(int val) +{ + static char buffer[80]; + char *r; + + switch(val) + { + case 0: + r = "normalCharging"; + break; + case 1: + r = "reverseCharging"; + break; + case 2: + r = "creditCardCharging"; + break; + case 3: + r = "callForwardingUnconditional"; + break; + case 4: + r = "callForwardingBusy"; + break; + case 5: + r = "callForwardingNoReply"; + break; + case 6: + r = "callDeflection"; + break; + case 7: + r = "callTransfer"; + break; + default: + sprintf(buffer, "unknown billing-id value %d!", val); + r = buffer; + } + return(r); +} + +/*---------------------------------------------------------------------------* + * invoke component + *---------------------------------------------------------------------------*/ +static void +F_1_1(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_1, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t invokeComponent\n"); + state = ST_EXP_INV_ID; + } +} + +/*---------------------------------------------------------------------------* + * return result + *---------------------------------------------------------------------------*/ +static void +F_1_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_2, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t returnResult\n"); + state = ST_EXP_RR_INV_ID; + } +} +/*---------------------------------------------------------------------------* + * return error + *---------------------------------------------------------------------------*/ +static void +F_1_3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_3, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t returnError\n"); + state = ST_EXP_NIX; + } +} +/*---------------------------------------------------------------------------* + * reject + *---------------------------------------------------------------------------*/ +static void +F_1_4(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_1_4, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t reject\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * invoke component: invoke id + *---------------------------------------------------------------------------*/ +static void +F_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_2, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t InvokeIdentifier = %d\n", val); + state = ST_EXP_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * return result: invoke id + *---------------------------------------------------------------------------*/ +static void +F_RR2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR2, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t InvokeIdentifier = %d\n", val); + state = ST_EXP_RR_OP_VAL; + } +} + +/*---------------------------------------------------------------------------* + * invoke component: operation value + *---------------------------------------------------------------------------*/ +static void +F_3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_3, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t Operation Value = %s (%d)\n", opval_str(val), val); + state = ST_EXP_INFO; + } +} + +/*---------------------------------------------------------------------------* + * return result: operation value + *---------------------------------------------------------------------------*/ +static void +F_RR3(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RR3, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t Operation Value = %s (%d)\n", opval_str(val), val); + state = ST_EXP_RR_RESULT; + } +} + +/*---------------------------------------------------------------------------* + * return result: RESULT + *---------------------------------------------------------------------------*/ +static void +F_RRR(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_RRR, val = %d\n", val); +#endif + state = ST_EXP_NIX; +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t specificChargingUnits\n"); + state = ST_EXP_RUL; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4_1(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_1, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t freeOfCharge\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_4_2(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_4_2, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t chargeNotAvailable\n"); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_5(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_5, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t recordedUnitsList [1]\n"); + state = ST_EXP_RU; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_6(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_6, val = %d\n", val); +#endif + if(val == -1) + { + sprintf((pbuf+strlen(pbuf)), "\t RecordedUnits\n"); + state = ST_EXP_RNOU; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_7(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_7, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t NumberOfUnits = %d\n", val); + state = ST_EXP_TOCI; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_8(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_8, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t typeOfChargingInfo = %s\n", val == 0 ? "subTotal" : "total"); + state = ST_EXP_DBID; + } +} + +/*---------------------------------------------------------------------------* + * + *---------------------------------------------------------------------------*/ +static void +F_9(char *pbuf, int val) +{ +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: exec F_9, val = %d\n", val); +#endif + if(val != -1) + { + sprintf((pbuf+strlen(pbuf)), "\t AOCDBillingId = %s (%d)\n", bid_str(val), val); + state = ST_EXP_NIX; + } +} + +/*---------------------------------------------------------------------------* + * state table + *---------------------------------------------------------------------------*/ +static struct statetab { + int currstate; /* input: current state we are in */ + int form; /* input: current tag form */ + int class; /* input: current tag class */ + int code; /* input: current tag code */ + void (*func)(char *,int); /* output: func to exec */ +} statetab[] = { + +/* current state tag form tag class tag code function */ +/* --------------------- ---------------------- ---------------------- ---------------------- ----------------*/ + +/* invoke */ + + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_1_1 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 2, F_1_2 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 3, F_1_3 }, + {ST_EXP_COMP_TYP, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 4, F_1_4 }, + {ST_EXP_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_2 }, + {ST_EXP_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_3 }, + {ST_EXP_INFO, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_4 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_NULL, F_4_1 }, + {ST_EXP_INFO, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 1, F_4_2 }, + {ST_EXP_RUL, FAC_TAGFORM_CON, FAC_TAGCLASS_COS, 1, F_5 }, + {ST_EXP_RU, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SEQ, F_6 }, + {ST_EXP_RNOU, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_7 }, + {ST_EXP_TOCI, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 2, F_8 }, + {ST_EXP_DBID, FAC_TAGFORM_PRI, FAC_TAGCLASS_COS, 3, F_9 }, + +/* return result */ + + {ST_EXP_RR_INV_ID, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_RR2 }, + {ST_EXP_RR_OP_VAL, FAC_TAGFORM_PRI, FAC_TAGCLASS_UNI, FAC_CODEUNI_INT, F_RR3 }, + {ST_EXP_RR_RESULT, FAC_TAGFORM_CON, FAC_TAGCLASS_UNI, FAC_CODEUNI_SET, F_RRR }, + +/* end */ + + {-1, -1, -1, -1, NULL } +}; + +/*---------------------------------------------------------------------------* + * state decode for do_component + *---------------------------------------------------------------------------*/ +static void +next_state(char *pbuf, int class, int form, int code, int val) +{ + int i; + +#ifdef ST_DEBUG + sprintf((pbuf+strlen(pbuf)), "next_state: class=%d, form=%d, code=%d, val=%d\n", class, form, code, val); +#endif + + for(i=0; ; i++) + { + if((statetab[i].currstate > state) || + (statetab[i].currstate == -1)) + { + break; + } + + if((statetab[i].currstate == state) && + (statetab[i].form == form) && + (statetab[i].class == class) && + (statetab[i].code == code)) + { + (*statetab[i].func)(pbuf, val); + break; + } + } +} + +/* EOF */ + diff --git a/usr.sbin/i4b/isdntrace/q932_fac.h b/usr.sbin/i4b/isdntrace/q932_fac.h new file mode 100644 index 0000000..feae448 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/q932_fac.h @@ -0,0 +1,174 @@ +/* + * Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * q932_fac.h - facility header file + * --------------------------------- + * + * $Id: q932_fac.h,v 1.4 1998/12/05 18:04:24 hm Exp $ + * + * last edit-date: [Sat Dec 5 18:21:17 1998] + * + *--------------------------------------------------------------------------- + * + * - Q.932 (03/93) Generic Procedures for the Control of + * ISDN Supplementaty Services + * - Q.950 (03/93) Supplementary Services Protocols, Structure and + * General Principles + * - ETS 300 179 (10/92) Advice Of Charge: charging information during + * the call (AOC-D) supplementary service Service description + * - ETS 300 180 (10/92) Advice Of Charge: charging information at the + * end of call (AOC-E) supplementary service Service description + * - ETS 300 181 (04/93) Advice Of Charge (AOC) supplementary service + * Functional capabilities and information flows + * - ETS 300 182 (04/93) Advice Of Charge (AOC) supplementary service + * Digital Subscriber Signalling System No. one (DSS1) protocol + * - X.208 Specification of Abstract Syntax Notation One (ASN.1) + * - X.209 Specification of Basic Encoding Rules for + * Abstract Syntax Notation One (ASN.1) + * - "ASN.1 Abstract Syntax Notation One", Walter Gora, DATACOM-Verlag + * 1992, 3rd Edition (ISBN 3-89238-062-7) (german !) + * + *---------------------------------------------------------------------------*/ + +/* #define FAC_DEBUG */ +/* #define ST_DEBUG */ + +/* protocols */ +#define FAC_PROTO_ROP 0x11 +#define FAC_PROTO_CMIP 0x12 +#define FAC_PROTO_ACSE 0x13 + +/* tag classes */ +#define FAC_TAGCLASS_UNI 0x00 +#define FAC_TAGCLASS_APW 0x01 +#define FAC_TAGCLASS_COS 0x02 +#define FAC_TAGCLASS_PRU 0x03 + +/* tag forms */ +#define FAC_TAGFORM_PRI 0x00 +#define FAC_TAGFORM_CON 0x01 + +/* class UNIVERSAL values */ +#define FAC_CODEUNI_BOOL 1 +#define FAC_CODEUNI_INT 2 +#define FAC_CODEUNI_BITS 3 +#define FAC_CODEUNI_OCTS 4 +#define FAC_CODEUNI_NULL 5 +#define FAC_CODEUNI_OBJI 6 +#define FAC_CODEUNI_OBJD 7 +#define FAC_CODEUNI_EXT 8 +#define FAC_CODEUNI_REAL 9 +#define FAC_CODEUNI_ENUM 10 +#define FAC_CODEUNI_R11 11 +#define FAC_CODEUNI_R12 12 +#define FAC_CODEUNI_R13 13 +#define FAC_CODEUNI_R14 14 +#define FAC_CODEUNI_R15 15 +#define FAC_CODEUNI_SEQ 16 +#define FAC_CODEUNI_SET 17 +#define FAC_CODEUNI_NSTR 18 +#define FAC_CODEUNI_PSTR 19 +#define FAC_CODEUNI_TSTR 20 +#define FAC_CODEUNI_VSTR 21 +#define FAC_CODEUNI_ISTR 22 +#define FAC_CODEUNI_UTIME 23 +#define FAC_CODEUNI_GTIME 24 +#define FAC_CODEUNI_GSTR 25 +#define FAC_CODEUNI_VISTR 26 +#define FAC_CODEUNI_GNSTR 27 + +/* operation values */ +#define FAC_OPVAL_UUS 1 +#define FAC_OPVAL_CUG 2 +#define FAC_OPVAL_MCID 3 +#define FAC_OPVAL_BTPY 4 +#define FAC_OPVAL_ETPY 5 +#define FAC_OPVAL_ECT 6 + +#define FAC_OPVAL_DIV_ACT 7 +#define FAC_OPVAL_DIV_DEACT 8 +#define FAC_OPVAL_DIV_ACTSN 9 +#define FAC_OPVAL_DIV_DEACTSN 10 +#define FAC_OPVAL_DIV_INTER 11 +#define FAC_OPVAL_DIV_INFO 12 +#define FAC_OPVAL_DIV_CALLDEF 13 +#define FAC_OPVAL_DIV_CALLRER 14 +#define FAC_OPVAL_DIV_LINF2 15 +#define FAC_OPVAL_DIV_INVS 16 +#define FAC_OPVAL_DIV_INTER1 17 +#define FAC_OPVAL_DIV_LINF1 18 +#define FAC_OPVAL_DIV_LINF3 19 + +#define FAC_OPVAL_ER_CRCO 20 +#define FAC_OPVAL_ER_MGMT 21 +#define FAC_OPVAL_ER_CANC 22 + +#define FAC_OPVAL_MLPP_QUERY 24 +#define FAC_OPVAL_MLPP_CALLR 25 +#define FAC_OPVAL_MLPP_CALLP 26 + +#define FAC_OPVAL_AOC_REQ 30 +#define FAC_OPVAL_AOC_S_CUR 31 +#define FAC_OPVAL_AOC_S_SPC 32 +#define FAC_OPVAL_AOC_D_CUR 33 +#define FAC_OPVAL_AOC_D_UNIT 34 +#define FAC_OPVAL_AOC_E_CUR 35 +#define FAC_OPVAL_AOC_E_UNIT 36 +#define FAC_OPVAL_AOC_IDOFCRG 37 + +#define FAC_OPVAL_CONF_BEG 40 +#define FAC_OPVAL_CONF_ADD 41 +#define FAC_OPVAL_CONF_SPLIT 42 +#define FAC_OPVAL_CONF_DROP 43 +#define FAC_OPVAL_CONF_ISOLATE 44 +#define FAC_OPVAL_CONF_REATT 45 +#define FAC_OPVAL_CONF_PDISC 46 +#define FAC_OPVAL_CONF_FCONF 47 +#define FAC_OPVAL_CONF_END 48 +#define FAC_OPVAL_CONF_IDCFE 49 + +#define FAC_OPVAL_REVC_REQ 60 + +enum states { + ST_EXP_COMP_TYP, + ST_EXP_INV_ID, + ST_EXP_OP_VAL, + ST_EXP_INFO, + ST_EXP_RUL, + ST_EXP_RU, + ST_EXP_RNOU, + ST_EXP_TOCI, + ST_EXP_DBID, + + ST_EXP_RR_INV_ID, + ST_EXP_RR_OP_VAL, + ST_EXP_RR_RESULT, + + ST_EXP_NIX +}; + +/* EOF */ + diff --git a/usr.sbin/i4b/isdntrace/trace.c b/usr.sbin/i4b/isdntrace/trace.c new file mode 100644 index 0000000..a9dde80 --- /dev/null +++ b/usr.sbin/i4b/isdntrace/trace.c @@ -0,0 +1,809 @@ +/* + * Copyright (c) 1996, 1998 Hellmuth Michaelis. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *---------------------------------------------------------------------------* + * + * trace.c - print traces of D (B) channel activity for isdn4bsd + * ------------------------------------------------------------- + * + * $Id: trace.c,v 1.10 1998/10/19 12:32:21 hm Exp $ + * + * last edit-date: [Mon Oct 19 14:30:58 1998] + * + * -hm rewriting for isic and new trace format + * -hm new option -f, use automatic name for -o + * -hm changed default option setting + * -hm multi unit support + * -hm analyzer functionality + * -hm binary record/playback + * -hm -p option + * -hm cleanup + * -hm adding date to timestamp field + * -hm reopen files on SIGUSR1 for rotation + * -hm Joerg reported a bug with commandline options + * -hm I.430 INFO signals from layer 1 + * + *---------------------------------------------------------------------------*/ + +#include "trace.h" + +unsigned char buf[BSIZE]; +FILE *Fout = NULL; +FILE *BP = NULL; +int outflag = 1; +int header = 1; +int print_q921 = 1; +int unit = 0; +int dchan = 0; +int bchan = 0; +int traceon = 0; +int analyze = 0; +int Rx = RxUDEF; +int Tx = TxUDEF; +int f; +int Bopt = 0; +int Popt = 0; +int bpopt = 0; +int info = 0; +int Fopt = 0; + +static char outfilename[1024]; +static char BPfilename[1024]; +static struct stat fst; + +static void dumpbuf( int n, unsigned char *buf, i4b_trace_hdr_t *hdr, int raw ); +static int switch_driver( int value, int rx, int tx ); +static void usage( void ); +static void exit_hdl( void ); +static void reopenfiles( int ); + +/*---------------------------------------------------------------------------* + * usage instructions + *---------------------------------------------------------------------------*/ +void +usage(void) +{ + fprintf(stderr,"\n"); + fprintf(stderr,"isdntrace - i4b package ISDN trace facility for passive cards (%02d.%02d.%d)\n", VERSION, REL, STEP); + fprintf(stderr,"usage: isdntrace -a -b -d -f <file> -h -i -l -n <val> -o -p <file> -r -u <unit>\n"); + fprintf(stderr," -B -F -P -R <unit> -T <unit>\n"); + fprintf(stderr," -a analyzer mode ................................... (default off)\n"); + fprintf(stderr," -b switch B channel trace on ....................... (default off)\n"); + fprintf(stderr," -d switch D channel trace off ....................... (default on)\n"); + fprintf(stderr," -f <file> write output to file filename ............ (default %s0)\n", TRACE_FILE_NAME); + fprintf(stderr," -h don't print header for each message ............. (default off)\n"); + fprintf(stderr," -i print I.430 (layer 1) INFO signals .............. (default off)\n"); + fprintf(stderr," -l don't decode low layer Q.921 messages ........... (default off)\n"); + fprintf(stderr," -n <val> process packet if it is longer than <val> octetts . (default 0)\n"); + fprintf(stderr," -o don't write output to a file .................... (default off)\n"); + fprintf(stderr," -p <file> specify filename for -B and -P ........ (default %s0)\n", BIN_FILE_NAME); + fprintf(stderr," -r don't print raw hex/ASCII dump of protocol ...... (default off)\n"); + fprintf(stderr," -u <unit> specify controller unit number ............... (default unit 0)\n"); + fprintf(stderr," -B write binary trace data to file filename ........ (default off)\n"); + fprintf(stderr," -F with -P and -p: wait for more data at EOF ....... (default off)\n"); + fprintf(stderr," -P playback from binary trace data file ............ (default off)\n"); + fprintf(stderr," -R <unit> analyze Rx controller unit number (for -a) ... (default unit %d)\n", RxUDEF); + fprintf(stderr," -T <unit> analyze Tx controller unit number (for -a) ... (default unit %d)\n", TxUDEF); + fprintf(stderr,"\n"); + exit(1); +} + +/*---------------------------------------------------------------------------* + * main + *---------------------------------------------------------------------------*/ +int +main(int argc, char *argv[]) +{ + extern int optind; + extern int opterr; + extern char *optarg; + char devicename[80]; + char headerbuf[256]; + + int n; + int c; + char *b; + + int enable_trace = TRACE_D_RX | TRACE_D_TX; + char *outfile = TRACE_FILE_NAME; + char *binfile = BIN_FILE_NAME; + int outfileset = 0; + int raw = 1; + int noct = -1; + time_t tm; + i4b_trace_hdr_t *ithp = NULL; + int l; + static struct stat fstnew; + + b = &buf[sizeof(i4b_trace_hdr_t)]; + + while( (c = getopt(argc, argv, "abdf:hiln:op:ru:BFPR:T:?")) != EOF) + { + switch(c) + { + case 'a': + analyze = 1; + break; + + case 'b': + enable_trace |= (TRACE_B_RX | TRACE_B_TX); + break; + + case 'd': + enable_trace &= (~(TRACE_D_TX | TRACE_D_RX)); + break; + + case 'o': + outflag = 0; + break; + + case 'f': + outfile = optarg; + outfileset = 1; + break; + + case 'n': + noct = atoi(optarg); + break; + + case 'h': + header = 0; + break; + + case 'i': + enable_trace |= TRACE_I; + info = 1; + break; + + case 'l': + print_q921 = 0; + break; + + case 'p': + binfile = optarg; + bpopt = 1; + break; + + case 'r': + raw = 0; + break; + + case 'u': + unit = atoi(optarg); + if(unit < 0 || unit >= MAX_CONTROLLERS) + usage(); + break; + + case 'B': + Bopt = 1; + break; + + case 'F': + Fopt = 1; + break; + + case 'P': + Popt = 1; + break; + + case 'R': + Rx = atoi(optarg); + if(Rx < 0 || Rx >= MAX_CONTROLLERS) + usage(); + break; + + case 'T': + Tx = atoi(optarg); + if(Tx < 0 || Tx >= MAX_CONTROLLERS) + usage(); + break; + + case '?': + default: + usage(); + break; + } + } + + if(enable_trace == 0) + usage(); + + if(Bopt && Popt) + usage(); + + atexit(exit_hdl); + + if(Bopt) + { + if(bpopt) + sprintf(BPfilename, "%s", binfile); + else + sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit); + + if((BP = fopen(BPfilename, "r")) != NULL) + { + char buffer[1024]; + fclose(BP); + sprintf(buffer, "%s%s", BPfilename, TRACE_FILE_NAME_BAK); + rename(BPfilename, buffer); + } + if((BP = fopen(BPfilename, "w")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting file [%s] to unbuffered", BPfilename); + perror(buffer); + exit(1); + } + } + + if(Popt) + { + if(bpopt) + sprintf(BPfilename, "%s", binfile); + else + sprintf(BPfilename, "%s%d", BIN_FILE_NAME, unit); + + if((BP = fopen(BPfilename, "r")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + if(Fopt) + { + if(fstat(fileno(BP), &fst)) + { + char buffer[80]; + sprintf(buffer, "Error fstat file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + } + else + { + sprintf(devicename, "%s%d", I4BTRC_DEVICE, unit); + + if((f = open(devicename, O_RDWR)) < 0) + { + char buffer[80]; + + sprintf(buffer, "Error opening trace device [%s]", devicename); + perror(buffer); + exit(1); + } + } + + if(outflag) + { + if(outfileset == 0) + sprintf(outfilename, "%s%d", TRACE_FILE_NAME, unit); + else + strcpy(outfilename, outfile); + + + if((Fout = fopen(outfilename, "r")) != NULL) + { + char buffer[1024]; + fclose(Fout); + sprintf(buffer, "%s%s", outfilename, TRACE_FILE_NAME_BAK); + rename(outfilename, buffer); + } + + if((Fout = fopen(outfilename, "w")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error opening file [%s]", outfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting file [%s] to unbuffered", outfile); + perror(buffer); + exit(1); + } + } + + if((setvbuf(stdout, (char *)NULL, _IOLBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error setting stdout to line-buffered"); + perror(buffer); + exit(1); + } + + if(!Popt) + { + if((switch_driver(enable_trace, Rx, Tx)) == -1) + exit(1); + else + traceon = 1; + } + + signal(SIGHUP, SIG_IGN); /* ignore hangup signal */ + signal(SIGUSR1, reopenfiles); /* rotate logfile(s) */ + + time(&tm); + + if(analyze) + { + sprintf(headerbuf, "\n==== isdnanalyze controller rx #%d - tx #%d ==== started %s", + Rx, Tx, ctime(&tm)); + } + else + { + sprintf(headerbuf, "\n=========== isdntrace controller #%d =========== started %s", + unit, ctime(&tm)); + } + + printf("%s", headerbuf); + + if(outflag) + fprintf(Fout, "%s", headerbuf); + + for (;;) + { + if(Popt == 0) + { + n = read(f, buf, BSIZE); + + if(Bopt) + { + if((fwrite(buf, 1, n, BP)) != n) + { + char buffer[80]; + sprintf(buffer, "Error writing file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + + n -= sizeof(i4b_trace_hdr_t); + } + else + { +again: + if((fread(buf, 1, sizeof(i4b_trace_hdr_t), BP)) != sizeof(i4b_trace_hdr_t)) + { + if(feof(BP)) + { + if(Fopt) + { + if(ferror(BP)) + { + char buffer[80]; + sprintf(buffer, "Error reading hdr from file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + usleep(250000); + clearerr(BP); + + if(stat(BPfilename, &fstnew) != -1) + { + if((fst.st_ino != fstnew.st_ino) || + (fstnew.st_nlink == 0)) + { + if((BP = freopen(BPfilename, "r", BP)) == NULL) + { + char buffer[80]; + sprintf(buffer, "Error reopening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + stat(BPfilename, &fst); + } + } + goto again; + } + else + { + printf("\nEnd of playback input file reached.\n"); + exit(0); + } + } + else + { + char buffer[80]; + sprintf(buffer, "Error reading hdr from file [%s]", BPfilename); + perror(buffer); + exit(1); + } + } + + ithp = (i4b_trace_hdr_t *)buf; + l = ithp->length - sizeof(i4b_trace_hdr_t); + + if((n = fread(buf+sizeof(i4b_trace_hdr_t), 1, l , BP)) != l) + { + char buffer[80]; + sprintf(buffer, "Error reading data from file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + } + + if((n > 0) && (n > noct)) + { + dumpbuf(n, b, (i4b_trace_hdr_t *)buf, raw); + } + } +} + +/*---------------------------------------------------------------------------* + * format header into static buffer, return buffer address + *---------------------------------------------------------------------------*/ +char * +fmt_hdr(i4b_trace_hdr_t *hdr, int frm_len) +{ + struct tm *s; + static char hbuf[256]; + int i = 0; + + s = localtime(&(hdr->time.tv_sec)); + + if(hdr->type == TRC_CH_I) /* Layer 1 INFO's */ + { + sprintf(hbuf,"\n-- %s - unit:%d ---------------- time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%6u ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec); + } + else + { + if(hdr->trunc > 0) + { + sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%6u - length:%d (%d) ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + hdr->count, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec, + frm_len, + hdr->trunc); + } + else + { + sprintf(hbuf,"\n-- %s - unit:%d - frame:%6.6u - time:%2.2d.%2.2d %2.2d:%2.2d:%2.2d.%6u - length:%d ", + ((hdr->dir) ? "NT->TE" : "TE->NT"), + hdr->unit, + hdr->count, + s->tm_mday, + s->tm_mon + 1, + s->tm_hour, + s->tm_min, + s->tm_sec, + (u_int32_t)hdr->time.tv_usec, + frm_len); + } + } + + for(i=strlen(hbuf); i <= NCOLS;) + hbuf[i++] = '-'; + + hbuf[i++] = '\n'; + hbuf[i] = '\0'; + + return(hbuf); +} + +/*---------------------------------------------------------------------------* + * decode protocol and output to file(s) + *---------------------------------------------------------------------------*/ +static void +dumpbuf(int n, unsigned char *buf, i4b_trace_hdr_t *hdr, int raw) +{ + static char l1buf[128]; + static unsigned char l2buf[32000]; + static unsigned char l3buf[32000]; + int cnt; + int nsave = n; + char *pbuf; + int i, j; + + l1buf[0] = '\0'; + l2buf[0] = '\0'; + l3buf[0] = '\0'; + + switch(hdr->type) + { + case TRC_CH_I: /* Layer 1 INFO's */ + pbuf = &l1buf[0]; + + switch(buf[0]) + { + case INFO0: + sprintf((pbuf+strlen(pbuf)),"I430: INFO0 (No Signal)\n"); + break; + + case INFO1_8: + sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 8, from TE)\n"); + break; + + case INFO1_10: + sprintf((pbuf+strlen(pbuf)),"I430: INFO1 (Activation Request, Priority = 10, from TE)\n"); + break; + + case INFO2: + sprintf((pbuf+strlen(pbuf)),"I430: INFO2 (Pending Activation, from NT)\n"); + break; + + case INFO3: + sprintf((pbuf+strlen(pbuf)),"I430: INFO3 (Synchronized, from TE)\n"); + break; + + case INFO4_8: + sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 8/9, from NT)\n"); + break; + + case INFO4_10: + sprintf((pbuf+strlen(pbuf)),"I430: INFO4 (Activated, Priority = 10/11, from NT)\n"); + break; + + default: + sprintf((pbuf+strlen(pbuf)),"I430: ERROR, invalid INFO value 0x%x!\n", buf[0]); + break; + } + break; + + case TRC_CH_D: /* D-channel data */ + + cnt = decode_lapd(l2buf, n, buf, hdr->dir, raw, print_q921); + + n -= cnt; + buf += cnt; + + if(n) + { + switch(*buf) + { + case 0x40: + case 0x41: + decode_1tr6(l3buf, n, cnt, buf, raw); + break; + + default: + decode_q931(l3buf, n, cnt, buf, raw); + break; + } + } + break; + + default: /* B-channel data */ + + pbuf = &l2buf[0]; + + for (i = 0; i < n; i += 16) + { + sprintf((pbuf+strlen(pbuf)),"B%d:%.3x ", hdr->type, i); + + for (j = 0; j < 16; j++) + if (i + j < n) + sprintf((pbuf+strlen(pbuf)),"%02x ", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf))," "); + + sprintf((pbuf+strlen(pbuf))," "); + + for (j = 0; j < 16 && i + j < n; j++) + if (isprint(buf[i + j])) + sprintf((pbuf+strlen(pbuf)),"%c", buf[i + j]); + else + sprintf((pbuf+strlen(pbuf)),"."); + + sprintf((pbuf+strlen(pbuf)),"\n"); + } + break; + } + + if(header && ((l1buf[0] != '\0' || l2buf[0] != '\0') || (l3buf[0] != 0))) + { + char *p; + p = fmt_hdr(hdr, nsave); + printf("%s", p); + if(outflag) + fprintf(Fout, "%s", p); + } + + if(l1buf[0] != '\0') + { + printf("%s", l1buf); + if(outflag) + fprintf(Fout, "%s", l1buf); + } + + if(l2buf[0] != '\0') + { + printf("%s", l2buf); + if(outflag) + fprintf(Fout, "%s", l2buf); + } + + if(l3buf[0] != '\0') + { + printf("%s", l3buf); + if(outflag) + fprintf(Fout, "%s", l3buf); + } +} + +/*---------------------------------------------------------------------------* + * exit handler function to be called at program exit + *---------------------------------------------------------------------------*/ +void +exit_hdl() +{ + if(traceon) + switch_driver(TRACE_OFF, Rx, Tx); +} + +/*---------------------------------------------------------------------------* + * switch driver debugging output on/off + *---------------------------------------------------------------------------*/ +static int +switch_driver(int value, int rx, int tx) +{ + char buffer[80]; + int v = value; + + if(analyze == 0) + { + if(ioctl(f, I4B_TRC_SET, &v) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_SET, val = %d", v); + perror(buffer); + return(-1); + } + } + else + { + if(value == TRACE_OFF) + { + if(ioctl(f, I4B_TRC_RESETA, &v) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_RESETA - "); + perror(buffer); + return(-1); + } + } + else + { + i4b_trace_setupa_t tsa; + + tsa.rxunit = rx; + tsa.rxflags = value; + tsa.txunit = tx; + tsa.txflags = value; + + if(ioctl(f, I4B_TRC_SETA, &tsa) < 0) + { + sprintf(buffer, "Error ioctl I4B_TRC_SETA, val = %d", v); + perror(buffer); + return(-1); + } + } + } + return(0); +} + +/*---------------------------------------------------------------------------* + * reopen files to support rotating logfile(s) on SIGUSR1 + * + * based on an idea from Ripley (ripley@nostromo.in-berlin.de) + * + * close file and reopen it for append. this will be a nop + * if the previously opened file hasn't moved but will open + * a new one otherwise, thus enabling a rotation... + * + *---------------------------------------------------------------------------*/ +static void +reopenfiles(int dummy) +{ + if(outflag) + { + fclose(Fout); + + if((Fout = fopen(outfilename, "a")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error re-opening file [%s]", outfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(Fout, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error re-setting file [%s] to unbuffered", outfilename); + perror(buffer); + exit(1); + } + } + + if(Bopt) + { + + fclose(BP); + + if((BP = fopen(BPfilename, "a")) == NULL) + { + char buffer[80]; + + sprintf(buffer, "Error re-opening file [%s]", BPfilename); + perror(buffer); + exit(1); + } + + if((setvbuf(BP, (char *)NULL, _IONBF, 0)) != 0) + { + char buffer[80]; + + sprintf(buffer, "Error re-setting file [%s] to unbuffered", BPfilename); + perror(buffer); + exit(1); + } + } +} + + +/* EOF */ diff --git a/usr.sbin/i4b/isdntrace/trace.h b/usr.sbin/i4b/isdntrace/trace.h new file mode 100644 index 0000000..e4c5b5a --- /dev/null +++ b/usr.sbin/i4b/isdntrace/trace.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 1996, 1998 Hellmuth Michaelis. All rights reserved. + * + * Copyright (c) 1996 Gary Jennejohn. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the author nor the names of any co-contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * 4. Altered versions must be plainly marked as such, and must not be + * misrepresented as being the original software and/or documentation. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *--------------------------------------------------------------------------- + * + * trace.h - header file for isdn trace + * ------------------------------------ + * + * $Id: trace.h,v 1.7 1998/10/19 12:32:23 hm Exp $ + * + * last edit-date: [Mon Oct 19 14:27:21 1998] + * + * -hm splitting + * -hm new filenames + * + *---------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <fcntl.h> +#include <ctype.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/uio.h> +#include <sys/time.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/file.h> +#include <sys/stat.h> + +#include <machine/i4b_ioctl.h> +#include <machine/i4b_trace.h> + +#include "pcause_1tr6.h" /* obsolete german national ISDN */ +#include "pcause_q850.h" + +#define I4BTRC_DEVICE "/dev/i4btrc" /* trace device file */ +#define TRACE_FILE_NAME "isdntrace" /* default output filename */ +#define TRACE_FILE_NAME_BAK ".last" /* backup filename trailer */ +#define BIN_FILE_NAME "isdntracebin" /* default binary filename */ + +#define BSIZE 4096 /* read buffer size */ +#define NCOLS 80 /* screen width */ + +#define RxUDEF 0 /* analyze mode, default unit for receiver side */ +#define TxUDEF 1 /* analyze mode, default unit for transmitter side */ + +int decode_lapd(char *pbuf, int n, unsigned char *buf, int is_te, int raw, int printit); +void decode_q931(char *pbuf, int n, int off, unsigned char *buf, int raw); +void decode_1tr6(char *pbuf, int n, int off, unsigned char *buf, int raw); +char *print_error(int prot, unsigned char code); +int q931_facility(char *pbuf, unsigned char *buf); +int p_q931cause(char *pbuf, unsigned char *buf); +int p_q931address(char *pbuf, unsigned char *buf); +int p_q931bc(char *pbuf, unsigned char *buf); +int p_q931high_compat(char *pbuf, unsigned char *buf); +int q932_facility(char *pbuf, unsigned char *buf); + +/* EOF */ diff --git a/usr.sbin/i4b/man/Makefile b/usr.sbin/i4b/man/Makefile new file mode 100644 index 0000000..65248d6 --- /dev/null +++ b/usr.sbin/i4b/man/Makefile @@ -0,0 +1,5 @@ +MAN4 = i4b.4 i4bctl.4 i4bipr.4 i4bq921.4 i4bq931.4 i4brbch.4 i4btel.4 \ + i4btrc.4 isic.4 daic.4 i4bisppp.4 + +.include <bsd.prog.mk> + diff --git a/usr.sbin/i4b/man/daic.4 b/usr.sbin/i4b/man/daic.4 new file mode 100644 index 0000000..fc04797 --- /dev/null +++ b/usr.sbin/i4b/man/daic.4 @@ -0,0 +1,98 @@ +.\" Copyright (c) 1997 Martin Husemann <martin@rumolt.teuto.de> +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. The name of the author may not be used to endorse or promote products +.\" derived from this software withough specific prior written permission +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" $Id: daic.4,v 1.1 1998/02/03 12:43:07 hm Exp $ +.\" +.\" last edit-date: [Fri Jan 30 22:49:48 1998] +.\" +.\" -mh writing manual pages +.\" +.\" +.Dd January 30, 1998 +.Dt daic 4 +.Sh NAME +.Nm daic +.Nd isdn4bsd driver for EICON.Diehl active isdn cards +.Pp +The +.Nm +driver supports the old Diehl active cards: +.Em S, SX, SXn, SCOM +and +.Em QUADRO. +.Sh SYNOPSIS +.Pp +Use a config line like this +.Cd "daic0 at isa? iomem 0xd8000 irq 10" +.Pp +For a +.Em QUADRO +card use the same, the driver will detect the board type and use +all four ports, each attached as a controller of its own to the +ISDN4BSD system, which can be listed using the isdnctl utility. +.Sh DESCRIPTION +The +.Nm +driver interfaces the isdn card to the ISDN4BSD kernel subsystem. +All lower layer isdn control is handled by the card. This should +allow you to run any national isdn protocol delivered by EICON.Diehl +for your card, but the driver has only been tested with the DSS1 +protocol and some parts of the cards interface are isdn protocol +dependend. +.Pp +The +.Nm +driver is written to conform to the software interface documented +by Diehl in their +.Nm ISDN-Karten Benutzerhandbuch +from 1992. +.Sh MICROCODE DOWNLOAD +Every active card needs its own operating software before it can +work. You have to download this to the card before using it with +ISDN4BSD. Use the isdnctl utility to do this, i.e. call +.Nm "isdnctl -d te_etsi.sx 1" +to download the file +.Nm te_etsi.sx +to controller number 1. Use +.Nm "isdnctl -l" +to list all available controllers (and ports). You have to select the +correct isdn protocol file for your isdn interface, see the Diehl documentation +for details. +.Pp +The cards bootstrap process involves another file, which is independend +of the card type you use and the protocol you run. It is called +.Nm download.bin +in current versions of the Diehl software distribution and has to be +copied to the kernel compile directory under +.Nm dev/ic/microcode/daic +and converted into a header file used when compiling the kernel by running +.Nm make +in that directory. Your kernel compile will fail and remind you of this +if you forget to do this. Due to copright restrictions we cannot distribute +the driver with this file integrated. But if you own a card, you do have +the file (or can get it from the Diehl web server). +.Sh BUGS +The driver is not yet finished. It will only compile on NetBSD and +even there will not work. This should be fixed soon and the driver +will be ported to FreeBSD. +.Sh SEE ALSO +.Xr isdnctl 1 diff --git a/usr.sbin/i4b/man/i4b.4 b/usr.sbin/i4b/man/i4b.4 new file mode 100644 index 0000000..f285c08 --- /dev/null +++ b/usr.sbin/i4b/man/i4b.4 @@ -0,0 +1,108 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4b.4,v 1.6 1998/12/05 18:06:03 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:38:11 1998] +.\" +.Dd February 3, 1998 +.Dt i4b 4 +.Sh NAME +.Nm i4b +.Nd isdn4bsd call control ISDN driver +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4b\&" +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +device driver is used by the +.Xr isdnd 8 +daemon to exchange messages with the isdn4bsd kernel part for the purpose +of call establishment, control and disconnection and to access various +control and status informations. +.Pp +The messages and message parameters are documented in the include +file +.Em /usr/include/machine/i4b_ioctl.h . +.Pp +The available ioctl's are: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar I4B_CDID_REQ +Request a unique Call Description IDentifier (cdid) which identifies +uniquely a single interaction of the local D channel with the exchange. +.It Ar I4B_CONNECT_REQ +Actively request a call setup to a remote ISDN subscriber. +.It Ar I4B_CONNECT_RESP +Respond to an incoming call, either accept, reject or ignore it. +.It Ar I4B_DISCONNECT_REQ +Actively terminate a connection. +.It Ar I4B_CTRL_INFO_REQ +Request information about an installed ISDN controller card. +.It Ar I4B_DIALOUT_RESP +Give information about call setup to driver who requested dialing out. +.It Ar I4B_TIMEOUT_UPD +Update the kernels timeout value(s) in case of dynamically calculated +shorthold mode timing changes. +.It Ar I4B_UPDOWN_IND +Inform the kernel userland drivers about interface soft up/down status +changes. +.It Ar I4B_CTRL_DOWNLOAD +Download firmware to active card(s). +.It Ar I4B_ACTIVE_DIAGNOSTIC +Return diagnostic information from active cards. +.El +.Pp +Status and event messages available from the kernel are: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar MSG_CONNECT_IND +An incoming call from a remote ISDN user is indicated. +.It Ar MSG_CONNECT_ACTIVE_IND +After an incoming call has been accepted locally or an outgoing call has +been accepted by a remote, the exchange signaled an active connection +and the corresponding B-channel is switched through. +.It Ar MSG_DISCONNECT_IND +A call was terminated. +.It Ar MSG_DIALOUT_IND +A userland interface driver requests the daemon to dial out (typically a +network interface when a packet arrives in its send queue). +.It Ar MSG_IDLE_TIMEOUT_IND +A call was terminated by the isdn4bsd kernel driver because a B-channel +idle timeout occurred. +.It Ar MSG_ACCT_IND +Accounting information from a network driver. +.It Ar MSG_CHARGING_IND +Charging information from the kernel. +.El +.Pp +.Sh SEE ALSO +.Xr isdnd 8 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4bctl.4 b/usr.sbin/i4b/man/i4bctl.4 new file mode 100644 index 0000000..fa5fccd --- /dev/null +++ b/usr.sbin/i4b/man/i4bctl.4 @@ -0,0 +1,50 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4bctl.4,v 1.4 1998/12/05 18:06:04 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:38:22 1998] +.\" +.Dd February 3, 1998 +.Dt i4bctl 4 +.Sh NAME +.Nm i4bctl +.Nd control device for the isdn4bsd kernel part +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4bctl\&" +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +.Nm +is used by the +.Xr isdndebug 8 +utility to get and set the current debugging level and other information +of the isdn4bsd package kernel ISDN handling layers. +.Sh SEE ALSO +.Xr isdndebug 8 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4bipr.4 b/usr.sbin/i4b/man/i4bipr.4 new file mode 100644 index 0000000..f4cdeac --- /dev/null +++ b/usr.sbin/i4b/man/i4bipr.4 @@ -0,0 +1,98 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4bipr.4,v 1.8 1998/12/05 18:06:06 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:38:34 1998] +.\" +.Dd July 6, 1998 +.Dt i4bipr 4 +.Sh NAME +.Nm i4bipr +.Nd isdn4bsd IP over ISDN B-channel network driver +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4bipr\&" Op count +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +driver interfaces the IP subsystem of the operating system with the +isdn4bsd package so that transport of IP packets over an ISDN link +is possible. +.Pp +The driver just packs IP packets without anything appended or prepended +into raw HDLC packets on the B channel and transfers them to a remote site. +IP packets received from the remote site are queued into the local IP +protocol stack. +.Pp +The format of the resulting packet on the B channel is: +.Pp +.Dl (HDLC opening flag) (IP-packet) (CRC) (HDLC closing flag) +.Pp +In the case where an IP packet for a remote site arrives in the driver and no +connection has been established yet, the driver communicates with the +.Xr isdnd 8 +daemon to establish a connection. +.Pp +The driver has support for interfacing to the +.Xr bpf 4 +subsystem for using +.Xr tcpdump 1 +with the +.Nm ipr +interfaces. +.Pp +The driver optionally (when compiled with the IPR_VJ option) provides Van +Jacobsen header compression, under control of the link0 and link1 options to +.Xr ifconfig 8 +: +.Pp +.Bl -tag -width 15n -offset indent -compact +.It link0 +Apply VJ compression to outgoing packets on this interface, and assume that +incoming packets require decompression. +.It link1 +Check incoming packets for Van Jacobsen compression; if they appear to be +compressed, automatically set link0. +.El +.Pp +The default values are +.Em on +for +.Em link1 +and +.Em off +for +.Em link0 . +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnd.rc 5 +.Xr bpf 4 +.Xr tcpdump 1 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4bisppp.4 b/usr.sbin/i4b/man/i4bisppp.4 new file mode 100644 index 0000000..ce65b82 --- /dev/null +++ b/usr.sbin/i4b/man/i4bisppp.4 @@ -0,0 +1,107 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4bisppp.4,v 1.9 1998/12/22 19:16:57 hm Exp $ +.\" +.\" last edit-date: [Tue Dec 22 20:15:08 1998] +.\" +.Dd December 22, 1998 +.Dt i4bisppp 4 +.Sh NAME +.Nm i4bisppp +.Nd isdn4bsd synchronous PPP over ISDN B-channel network driver +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4bisppp\&" Op count +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +driver interfaces the IP subsystem of the operating system with the +isdn4bsd package so that a transport of IP packets over an ISDN link +is possible. +.Pp +The driver is just a glue layer between Serge Vakulenko's sppp +backend and the ISDN4BSD package. +.Pp +In case an IP packet for a remote side arrives in the driver and no +connection is established yet, the driver communicates with the +.Xr isdnd 8 +daemon to establish a connection. +.Pp +The driver has support for interfacing to the +.Xr bpf 4 +subsystem for using +.Xr tcpdump 1 +with the +.Nm isp +interfaces. +.Pp +The +.Xr spppcontrol 8 +utility is used to configure all aspects of PPP required to connect to a +remote site. +.Sh LINK0 and LINK1 +The +.Em link0 +and +.Em link1 +flags given as parameters to +.Xr ifconfig 8 +have the following meaning for the +.Nm isp +devices: +.Bl -tag -width link0 -compact +.Pp +.It Li link0 +wait passively for connection +.Pp +.It Li link1 +auto-dial on output +.El +.Pp +The +.Em link0 +and +.Em link1 +flags are set to +.Em off +by default. +.Pp +See +.Xr sppp 4 +for a more detailed discussion of the flags, +.Pp +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnd.rc 5 +.Xr spppcontrol 8 +.Xr sppp 4 +.Xr bpf 4 +.Xr tcpdump 1 +.Sh AUTHOR +The +.Nm +device driver was written by Joerg Wunsch and then added to ISDN4BSD by Gary Jennejohn. +This manpage was written by Hellmuth Michaelis. He can be contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4bq921.4 b/usr.sbin/i4b/man/i4bq921.4 new file mode 100644 index 0000000..bb5bcfc --- /dev/null +++ b/usr.sbin/i4b/man/i4bq921.4 @@ -0,0 +1,49 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4bq921.4,v 1.5 1998/12/05 18:06:08 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:38:57 1998] +.\" +.Dd February 3, 1998 +.Dt i4bq921 4 +.Sh NAME +.Nm i4bq921 +.Nd isdn4bsd pseudo device driver handling the Q.921 protocol +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4bq921\&" +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +.Nm +is the ISDN D channel layer 2 handler. +.Sh STANDARDS +ITU Recommendation Q.920 and Q.921 +.Sh SEE ALSO +.Xr i4bq931 4 +.Sh AUTHOR +The +.Nm +driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4bq931.4 b/usr.sbin/i4b/man/i4bq931.4 new file mode 100644 index 0000000..7c8d155 --- /dev/null +++ b/usr.sbin/i4b/man/i4bq931.4 @@ -0,0 +1,49 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4bq931.4,v 1.5 1998/12/05 18:06:10 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:39:08 1998] +.\" +.Dd February 3, 1998 +.Dt i4bq931 4 +.Sh NAME +.Nm i4bq931 +.Nd isdn4bsd pseudo device driver handling the Q.931 protocol +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4bq931\&" +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +.Nm +is the ISDN D channel layer 2 handler. +.Sh STANDARDS +ITU Recommendation Q.930 and Q.931 +.Sh SEE ALSO +.Xr i4bq921 4 +.Sh AUTHOR +The +.Nm +driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4brbch.4 b/usr.sbin/i4b/man/i4brbch.4 new file mode 100644 index 0000000..b7ee3df --- /dev/null +++ b/usr.sbin/i4b/man/i4brbch.4 @@ -0,0 +1,50 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4brbch.4,v 1.5 1998/12/05 18:06:11 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:39:19 1998] +.\" +.Dd February 3, 1998 +.Dt i4brbch 4 +.Sh NAME +.Nm i4brbch +.Nd isdn4bsd ISDN Raw B-CHannel access driver +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4brbch\&" Op count +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +driver provides an interface to the raw untranslated B-channel. It is +part of the isdn4bsd package. +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnd.rc 5 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4btel.4 b/usr.sbin/i4b/man/i4btel.4 new file mode 100644 index 0000000..e5f6252 --- /dev/null +++ b/usr.sbin/i4b/man/i4btel.4 @@ -0,0 +1,52 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4btel.4,v 1.5 1998/12/05 18:06:12 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:39:31 1998] +.\" +.Dd February 3, 1998 +.Dt i4btel 4 +.Sh NAME +.Nm i4btel +.Nd isdn4bsd ISDN B-channel telephony interface driver +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4btel\&" Op count +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +driver provides an interface to the B-channel for telephony applications +and is currently used by the +.Xr isdnd 8 +for answering machine support. The driver is part of the isdn4bsd package. +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdnd.rc 5 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/i4btrc.4 b/usr.sbin/i4b/man/i4btrc.4 new file mode 100644 index 0000000..60b88ed --- /dev/null +++ b/usr.sbin/i4b/man/i4btrc.4 @@ -0,0 +1,52 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: i4btrc.4,v 1.5 1998/12/05 18:06:13 hm Exp $ +.\" +.\" last edit-date: [Sat Dec 5 18:39:42 1998] +.\" +.Dd February 3, 1998 +.Dt i4btrc 4 +.Sh NAME +.Nm i4btrc +.Nd isdn4bsd ISDN interface driver for D and B channel tracing +.Sh FreeBSD SYNOPSIS +.Cd pseudo-device \&"i4btrc\&" Op count +.Sh NetBSD SYNOPSIS +none +.Sh DESCRIPTION +The +.Nm +driver is used to add a header to the data got from the D and/or B channel +and queues it to be read and further processed by the +.Xr isdntrace 8 +utility. +.Sh SEE ALSO +.Xr isdnd 8 +.Xr isdntrace 8 +.Sh AUTHOR +The +.Nm +device driver and this manpage were written by Hellmuth Michaelis. He can be +contacted at hm@kts.org. diff --git a/usr.sbin/i4b/man/isic.4 b/usr.sbin/i4b/man/isic.4 new file mode 100644 index 0000000..0ba54d6 --- /dev/null +++ b/usr.sbin/i4b/man/isic.4 @@ -0,0 +1,380 @@ +.\" +.\" Copyright (c) 1997, 1998 Hellmuth Michaelis. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" $Id: isic.4,v 1.14 1998/12/22 19:12:13 hm Exp $ +.\" +.\" last edit-date: [Tue Dec 22 20:08:06 1998] +.\" +.Dd December 22, 1998 +.Dt isic 4 +.Sh NAME +.Nm isic +.Nd isdn4bsd Siemens ISDN Chipset device driver +.Sh FreeBSD SYNOPSIS +.Pp +For a Teles S0/8 or Niccy 1008 card: +.Cd options \&"TEL_S0_8\&" +.Cd "device isic0 at isa? iomem 0xd0000 net irq 5 flags 1 vector isicintr" +.Pp +For a Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 card: +.Cd options \&"TEL_S0_16\&" +.Cd "device isic0 at isa? port 0xd80 iomem 0xd0000 net irq 5 flags 2 vector isicintr" +.Pp +For a Teles S0/16.3 card: +.Cd options \&"TEL_S0_16_3\&" +.Cd "device isic0 at isa? port 0xd80 net irq 5 flags 3 vector isicintr" +.Pp +For an AVM A1 or AVM Fritz!Card classic: +.Cd options \&"AVM_A1\&" +.Cd "device isic0 at isa? port 0x340 net irq 5 flags 4 vector isicintr" +.Pp +For an AVM Fritz!Card PCMCIA: +.Cd options \&"AVM_A1_PCMCIA\&" +.Cd "device isic0 at isa? port 0x340 net irq 5 flags 10 vector isicintr" +.Pp +For a Teles S0/16.3 PnP card (PnP): +.Cd options \&"TEL_S0_16_3_P\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For a Creatix ISDN-S0 P&P card (PnP): +.Cd options \&"CRTX_S0_P\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For an USRobotics Sportster ISDN TA internal or Stollmann Tina-pp card: +.Cd options \&"USR_STI\&" +.Cd "device isic0 at isa? port 0x268 net irq 5 flags 7 vector isicintr" +.Pp +For an ITK micro ix1 card: +.Cd options \&"ITKIX1\&" +.Cd "device isic0 at isa? port 0x398 net irq 10 flags 18 vector isicintr" +.Pp +For a Dr. Neuhaus Niccy Go@ (PnP): +.Cd options \&"DRN_NGO\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For a Sedlbauer Win Speed card (PnP): +.Cd options \&"SEDLBAUER\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For a Dynalink IS64PH (PnP): +.Cd options \&"DYNALINK\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For an ELSA QuickStep 1000pro ISA (PnP): +.Cd options \&"ELSA_QS1ISA\&" +.Cd "device isic0 at isa? port ? net irq ? vector isicintr" +.Pp +For an ELSA QuickStep 1000pro PCI: +.Cd options \&"ELSA_QS1PCI\&" +.Cd "device isic0" +.Pp +.Ar FreeBSD PnP configuration: +.Pp +To be able to use PnP cards under FreeBSD, you have to add +.Pp +.Cd controller pnp0 +.Pp +to you kernel config file. More, it is recommended to add +.Pp +.Cd options \&"USERCONFIG\&" +.Cd options \&"USERCONFIG_BOOT\&" +.Pp +to your kernel config file to be able to adjust your PnP configuration +in case of trouble. +.Pp +See also: +.Xr pnp 4 +and +.Xr boot 8 +.Pp +.Sh NetBSD SYNOPSIS +On the ISA bus: +.Pp +For a Teles S0/8 or Niccy 1008 card: +.Cd options \&"TEL_S0_8\&" +.Cd "isic0 at isa? iomem 0xd0000 irq 5" +.Pp +For a Teles S0/16 or Creatix ISDN-S0 or Niccy 1016 card: +.Cd options \&"TEL_S0_16\&" +.Cd "isic0 at isa? port 0xd80 iomem 0xd0000 irq 5" +.Pp +For a Teles S0/16.3 card: +.Cd options \&"TEL_S0_16_3\&" +.Cd "isic0 at isa? port 0xd80 irq 5" +.Pp +For an AVM A1 or AVM Fritz card: +.Cd options \&"AVM_A1\&" +.Cd "isic0 at isa? port 0x340 irq 5" +.Pp +For an USRobotics Sportster ISDN TA internal or Stollmann Tina-pp card: +.Cd options \&"USR_STI\&" +.Cd "isic0 at isa? port 0x268 irq 5" +.Pp +For an ITK ix1 micro card: +.Cd options \&"ITKIX1\&" +.Cd "isic0 at isa? port 0x398 irq 10" +.Pp +On the ISAPNP bus: +.Pp +For a Teles S0/16.3 PnP card +.Cd options \&"TEL_S0_16_3_P\&" +.Cd "isic* at isapnp?" +.Pp +For a Creatix ISDN-S0 P&P card +.Cd options \&"CRTX_S0_P\&" +.Cd "isic* at isapnp?" +.Pp +For a Dr. Neuhaus Niccy GO@ +.Cd options \&"DRN_NGO\&" +.Cd "isic* at isapnp?" +.Pp +For an ELSA QuickStep 1000pro (ISA version): +.Cd options \&"ELSA_QS1ISA\&" +.Cd "isic* at isapnp?" +.Pp +For a Sedlbauer WinSpeed: +.Cd options \&"SEDLBAUER\&" +.Cd "isic* at isapnp?" +.Pp +For a Dynalink IS64PH: +.Cd options \&"DYNALINK\&" +.Cd "isic* at isapnp?" +.Pp +Cards on the PCI bus: +.Pp +For an ELSA QuickStep 1000pro (PCI version) +.Cd options \&"ELSA_QS1PCI\&" +.Cd "isic* at pci?" +.Pp +Cards on the PCMCIA or PCCARD bus: +.Pp +For an AVM Fritz!Card PCMCIA +.Cd options \&"AVM_PCMCIA\&" +.Cd "isic* at pcmcia? function ?" +.Pp +For an ELSA MicroLink ISDN/MC +.Cd options \&"ELSA_ISDNMC\&" +.Cd "isic* at pcmcia? function ?" +.Pp +For an ELSA MicroLink MC/all +.Cd options \&"ELSA_MCALL\&" +.Cd "isic* at pcmcia? function ?" +.Pp +.Sh DESCRIPTION +The +.Nm +driver provides D-channel layer 1 supports as specified in ITU Recommendation +I.430 and layer 1 support for the B-channel. +.Pp +The driver supports several 8 and 16bit passive ISDN cards from various +manufacturers which are all based upon the popular Siemens ISDN chipset +consisting of the ISDN Subscriber Access Controller ISAC (such as the +PEB2085 or PSB 2186) and the High-Level Serial Communications Controller +Extended HSCX (such as the SAB82525 or PSB21525). The newer IPAC chip +(which integrates an ISAC and a HSCX in one chip, with the added benefit +of larger FIFO buffers) is also supported. +.Pp +.Sh SUPPORTED CARDS +.Pp +.Bl -tag -width Ds -compact -offset +.It Ar Teles S0/8, Dr. Neuhaus Niccy 1008, Creatix ISDN-S0/8 +.Pp +The required (optional for NetBSD) +.Em flag +value is 1. +.Pp +Notice that this cards must not have a +.Em port +value in the config line. +.Pp +Valid interrupts are 2, 3, 4, 5, 6 and 7. +.Pp +The i/o ports are memory mapped and the memory start address may +be in the range 0xA0000 to 0xDF000 and uses 4kB of memory. +.Pp +.It Ar Teles S0/16, Creatix ISDN-S0, Dr. Neuhaus Niccy 1016 +.Pp +The required (optional under NetBSD) +.Em flag +value is 2. +.Pp +These boards have a jumper which specifies an i/o base address of either +0xd80, 0xe80 or 0xf80. The remaining necessary configuration values are then +programmed at run time by accessing this i/o port. +.Pp +Valid interrupts are 2, 3, 4, 5, 10, 11, 12 or 15. +.Pp +Valid memory start +addresses are 0xC0000, 0xC2000, 0xC4000, 0xC6000, 0xC8000, 0xCA000, 0xCC000, +0xCE000, 0xD0000, 0xD2000, 0xD4000, 0xD6000, 0xD8000, 0xDA000, 0xDC000 and +0xDE000. +.Pp +Notice: Although the Jumpers are labeled 0xd80, 0xe80 or 0xf80, they +also require i/o space at addresses 0x180, 0x280 or 0x380. +.Pp +.It Ar Teles S0/16.3 +.Pp +The required (optional under NetBSD) +.Em flag +value is 3. +.Pp +This card is completely i/o mapped and must not have an +.Em iomem +statement in the config line. +.Pp +Valid interrupts are 2, 5, 9, 10, 12 or 15. +.Pp +Notice: Although the switch positions are labeled 0x180, 0x280 and 0x380, +the card is to be configured at 0xd80, 0xe80 or 0xf80 respectively! +.Pp +.It Ar AVM A1, AVM Fritz!Card +.Pp +The required (optional under NetBSD) +.Em flag +value is 4. +.Pp +These boards have a jumper which specifies an i/o base address of either +0x200, 0x240, 0x300 or 0x340. +.Pp +Valid interrupt configurations are 3, 4, 5, 6, 7, 10, 11, 12 or 15. +.Pp +Older Versions of the AVM A1 also require setting of an IRQ jumper, newer +versions of this and the Fritz!Card only have an i/o base jumper and the +interrupt is setup at runtime by reprogramming a register. +.Pp +This card is completely i/o mapped and must not have an +.Em iomem +statement in the config line. +.Pp +.It Ar Teles S0/16.3 PnP +.Pp +Possible i/o port values are 0x580, 0x500 and 0x680. +Possible interrupt configurations are 3, 5, 7, 10, 11 and 12. +.Pp +The the card is auto-configured by the PnP kernel subsystem. +.Pp +.It Ar Creatix ISDN-S0 P&P +.Pp +Valid i/o port values are 0x120, 0x180 and 0x100. +.Pp +Valid interrupt configurations are 3, 5, 7, 10, 11 and 12. +.Pp +The card is auto-configured by the PnP kernel subsystem. +.Pp +.It Ar "3Com USRobotics Sportster ISDN TA intern and Stollmann Tina pp" +.Pp +The required (optional for NetBSD) +.Em flag +value is 7. +.Pp +Valid i/o port values are 0x200, 0x208, 0x210, 0x218, 0x220, 0x228, 0x230, +0x238, 0x240, 0x248, 0x250, 0x258, 0x260, 0x268, 0x270 and 0x278. +.Pp +Valid interrupt configurations are 5, 7, 10, 11, 12, 14, 15. +.Pp +Notice: this card has a strange address decoding scheme resulting in 64 +windows of some bytes length. Anyway, support for this card is good because +the manufacturer gave out technical docs for this card! +.Pp +.Pp +.It Ar "Dr. Neuhaus Niccy Go@" +.Pp +Valid i/o port values must be in the range 0x200 ... 0x3e0. +.Pp +Valid interrupt configurations are 3, 4, 5, 9, 10, 11, 12, 15. +.Pp +The card is auto-configured by the PnP kernel subsystem. +.Pp +.It Ar "Sedlbauer Win Speed" +.Pp +Valid i/o port values must be in the range 0x100 ... 0x3f0. (alignment 0x8, +len 0x8) +.Pp +Valid interrupt configurations are 3, 4, 5, 7, 10, 11, 12, 13, 15. +.Pp +The card is auto-configured by the PnP kernel subsystem. +.Em FreeBSD: +This card is PnP only, and so it can be configured using USERCONFIG +('man 4 pnp'). This can be done via +.Em /kernel.config +\&. For example: +.Pp +.Cd USERCONFIG +.Cd pnp 1 0 os enable port0 0x270 irq0 10 +.Cd quit +.Pp +.Pp +.It Ar "ELSA QuickStep 1000pro (ISA)" +.Pp +I/O port in the range 0x160 ... 0x360 (occupies 8 bytes). +.Pp +Valid interrupt configurations are 3, 4, 5, 7, 10, 11, 12, 15. +.Pp +The card is auto-configured by the PnP kernel subsystem. +.Pp +.Pp +.It Ar "ELSA QuickStep 1000pro-PCI" +.Pp +The card is auto-configured by the PCI kernel subsystem. +.Pp +.Pp +.It Ar "ITK ix1 micro" +.Pp +The required (optional under NetBSD) +.Em flag +value is 18. +.Pp +Valid i/o port values must be in the range (<unknown>). +.Pp +Valid interrupt configurations are (<unknown>). +.Pp +.Sh CAVEATS +Note that all of the boards with I/O ports actually use several ranges +of port addresses; Teles happen to refer to the 0xd80 range in their +documentation (the board also uses 0x180 etc.), while AVM happen to refer +to the 0x200 range in their documentation (the board also uses 0x600 etc.) +The driver matches the manufacturers' description for the purposes of +configuration, but of course makes use of all the ports in order to +operate the card. +.Pp +.Sh BUGS +Since there is no hardware documentation available from several manufacturers +for their boards, it is likely that there are many, many bugs left. + +.Sh STANDARDS +CCITT Recommendation I.430 + +.Sh SEE ALSO +.Xr i4bq921 4 +.Xr i4bq931 4 + +.Sh AUTHOR +The +.Nm +driver and this manpage were written by Hellmuth Michaelis. It is based +on earlier work of Arne Helme, Andrew Gordon and Gary Jennejohn. The author +can be contacted at hm@kts.org. +.Pp +The complete porting to and maintenance of NetBSD was done by Martin Husemann. +He can be contacted at martin@rumolt.teuto.de |