summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--share/Makefile2
-rw-r--r--share/isdn/0.g711a.uu322
-rw-r--r--share/isdn/1.g711a.uu322
-rw-r--r--share/isdn/2.g711a.uu277
-rw-r--r--share/isdn/3.g711a.uu322
-rw-r--r--share/isdn/4.g711a.uu322
-rw-r--r--share/isdn/5.g711a.uu368
-rw-r--r--share/isdn/6.g711a.uu277
-rw-r--r--share/isdn/7.g711a.uu231
-rw-r--r--share/isdn/8.g711a.uu322
-rw-r--r--share/isdn/9.g711a.uu231
-rw-r--r--share/isdn/Makefile20
-rw-r--r--share/isdn/beep.g711a.uu106
-rw-r--r--share/isdn/msg.g711a.uu1505
-rw-r--r--sys/conf/NOTES116
-rw-r--r--sys/conf/files36
-rw-r--r--sys/conf/files.i38626
-rw-r--r--sys/conf/options.i38638
-rw-r--r--sys/i386/conf/LINT116
-rw-r--r--sys/i386/conf/NOTES116
-rw-r--r--sys/i386/conf/files.i38626
-rw-r--r--sys/i386/conf/options.i38638
-rw-r--r--sys/i386/include/i4b_cause.h144
-rw-r--r--sys/i386/include/i4b_debug.h219
-rw-r--r--sys/i386/include/i4b_ioctl.h606
-rw-r--r--sys/i386/include/i4b_tel_ioctl.h52
-rw-r--r--sys/i386/include/i4b_trace.h91
-rw-r--r--sys/i4b/driver/i4b_ctl.c303
-rw-r--r--sys/i4b/driver/i4b_ipr.c1115
-rw-r--r--sys/i4b/driver/i4b_isppp.c710
-rw-r--r--sys/i4b/driver/i4b_rbch.c820
-rw-r--r--sys/i4b/driver/i4b_tel.c713
-rw-r--r--sys/i4b/driver/i4b_trace.c508
-rw-r--r--sys/i4b/include/i4b_cause.h144
-rw-r--r--sys/i4b/include/i4b_debug.h219
-rw-r--r--sys/i4b/include/i4b_global.h95
-rw-r--r--sys/i4b/include/i4b_ioctl.h606
-rw-r--r--sys/i4b/include/i4b_isdnq931.h166
-rw-r--r--sys/i4b/include/i4b_l1l2.h99
-rw-r--r--sys/i4b/include/i4b_l2l3.h116
-rw-r--r--sys/i4b/include/i4b_l3l4.h260
-rw-r--r--sys/i4b/include/i4b_mbuf.h51
-rw-r--r--sys/i4b/include/i4b_tel_ioctl.h52
-rw-r--r--sys/i4b/include/i4b_trace.h91
-rw-r--r--sys/i4b/layer1/i4b_avm_a1.c508
-rw-r--r--sys/i4b/layer1/i4b_avm_fritz_pcmcia.c504
-rw-r--r--sys/i4b/layer1/i4b_bchan.c484
-rw-r--r--sys/i4b/layer1/i4b_ctx_s0P.c366
-rw-r--r--sys/i4b/layer1/i4b_drn_ngo.c542
-rw-r--r--sys/i4b/layer1/i4b_dynalink.c438
-rw-r--r--sys/i4b/layer1/i4b_elsa_isdnmc.c305
-rw-r--r--sys/i4b/layer1/i4b_elsa_mcall.c251
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1i.c511
-rw-r--r--sys/i4b/layer1/i4b_elsa_qs1p.c458
-rw-r--r--sys/i4b/layer1/i4b_hscx.c672
-rw-r--r--sys/i4b/layer1/i4b_hscx.h301
-rw-r--r--sys/i4b/layer1/i4b_ipac.h199
-rw-r--r--sys/i4b/layer1/i4b_isac.c679
-rw-r--r--sys/i4b/layer1/i4b_isac.h391
-rw-r--r--sys/i4b/layer1/i4b_isic.c345
-rw-r--r--sys/i4b/layer1/i4b_isic_isa.c591
-rw-r--r--sys/i4b/layer1/i4b_isic_pci.c424
-rw-r--r--sys/i4b/layer1/i4b_isic_pcmcia.c164
-rw-r--r--sys/i4b/layer1/i4b_isic_pnp.c296
-rw-r--r--sys/i4b/layer1/i4b_itk_ix1.c430
-rw-r--r--sys/i4b/layer1/i4b_l1.c315
-rw-r--r--sys/i4b/layer1/i4b_l1.h438
-rw-r--r--sys/i4b/layer1/i4b_l1fsm.c546
-rw-r--r--sys/i4b/layer1/i4b_sws.c392
-rw-r--r--sys/i4b/layer1/i4b_tel_s016.c455
-rw-r--r--sys/i4b/layer1/i4b_tel_s0163.c432
-rw-r--r--sys/i4b/layer1/i4b_tel_s08.c389
-rw-r--r--sys/i4b/layer1/i4b_tel_s0P.c378
-rw-r--r--sys/i4b/layer1/i4b_usr_sti.c440
-rw-r--r--sys/i4b/layer1/isa_isic.c828
-rw-r--r--sys/i4b/layer1/isapnp_isic.c386
-rw-r--r--sys/i4b/layer1/isic_supio.c374
-rw-r--r--sys/i4b/layer1/pci_isic.c327
-rw-r--r--sys/i4b/layer1/pcmcia_isic.c358
-rw-r--r--sys/i4b/layer1/pcmcia_isic.h60
-rw-r--r--sys/i4b/layer2/i4b_iframe.c275
-rw-r--r--sys/i4b/layer2/i4b_l2.c390
-rw-r--r--sys/i4b/layer2/i4b_l2.h339
-rw-r--r--sys/i4b/layer2/i4b_l2fsm.c1593
-rw-r--r--sys/i4b/layer2/i4b_l2fsm.h82
-rw-r--r--sys/i4b/layer2/i4b_l2timer.c263
-rw-r--r--sys/i4b/layer2/i4b_lme.c160
-rw-r--r--sys/i4b/layer2/i4b_mbuf.c245
-rw-r--r--sys/i4b/layer2/i4b_sframe.c215
-rw-r--r--sys/i4b/layer2/i4b_tei.c322
-rw-r--r--sys/i4b/layer2/i4b_uframe.c308
-rw-r--r--sys/i4b/layer2/i4b_util.c312
-rw-r--r--sys/i4b/layer3/i4b_l2if.c642
-rw-r--r--sys/i4b/layer3/i4b_l3.h80
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.c1034
-rw-r--r--sys/i4b/layer3/i4b_l3fsm.h105
-rw-r--r--sys/i4b/layer3/i4b_l3timer.c347
-rw-r--r--sys/i4b/layer3/i4b_l4if.c339
-rw-r--r--sys/i4b/layer3/i4b_q931.c624
-rw-r--r--sys/i4b/layer3/i4b_q931.h116
-rw-r--r--sys/i4b/layer3/i4b_q932fac.c569
-rw-r--r--sys/i4b/layer3/i4b_q932fac.h167
-rw-r--r--sys/i4b/layer4/i4b_i4bdrv.c832
-rw-r--r--sys/i4b/layer4/i4b_l4.c897
-rw-r--r--sys/i4b/layer4/i4b_l4.h69
-rw-r--r--sys/i4b/layer4/i4b_l4mgmt.c467
-rw-r--r--sys/i4b/layer4/i4b_l4timer.c110
-rw-r--r--sys/i4b/tina-dd/README20
-rw-r--r--sys/i4b/tina-dd/i4b_tina_dd.c330
-rw-r--r--sys/i4b/tina-dd/i4b_tina_ioctl.h138
-rw-r--r--usr.sbin/Makefile3
-rw-r--r--usr.sbin/i4b/Makefile4
-rw-r--r--usr.sbin/i4b/Makefile.inc14
-rw-r--r--usr.sbin/i4b/alawulaw/Makefile7
-rw-r--r--usr.sbin/i4b/alawulaw/alaw2ulaw.170
-rw-r--r--usr.sbin/i4b/alawulaw/alaw2ulaw.c151
-rw-r--r--usr.sbin/i4b/alawulaw/ulaw2alaw.170
-rw-r--r--usr.sbin/i4b/isdnd/Makefile32
-rw-r--r--usr.sbin/i4b/isdnd/alias.c191
-rw-r--r--usr.sbin/i4b/isdnd/config.h61
-rw-r--r--usr.sbin/i4b/isdnd/controller.c329
-rw-r--r--usr.sbin/i4b/isdnd/curses.c633
-rw-r--r--usr.sbin/i4b/isdnd/dial.c153
-rw-r--r--usr.sbin/i4b/isdnd/exec.c280
-rw-r--r--usr.sbin/i4b/isdnd/fsm.c446
-rw-r--r--usr.sbin/i4b/isdnd/isdnd.8419
-rw-r--r--usr.sbin/i4b/isdnd/isdnd.acct.5108
-rw-r--r--usr.sbin/i4b/isdnd/isdnd.h754
-rw-r--r--usr.sbin/i4b/isdnd/isdnd.rates.5115
-rw-r--r--usr.sbin/i4b/isdnd/isdnd.rc.5642
-rw-r--r--usr.sbin/i4b/isdnd/log.c242
-rw-r--r--usr.sbin/i4b/isdnd/main.c707
-rw-r--r--usr.sbin/i4b/isdnd/monitor.c811
-rw-r--r--usr.sbin/i4b/isdnd/msghdl.c983
-rw-r--r--usr.sbin/i4b/isdnd/pathnames.h54
-rw-r--r--usr.sbin/i4b/isdnd/pcause.c227
-rw-r--r--usr.sbin/i4b/isdnd/process.c219
-rw-r--r--usr.sbin/i4b/isdnd/rates.c473
-rw-r--r--usr.sbin/i4b/isdnd/rc_config.c1140
-rw-r--r--usr.sbin/i4b/isdnd/rc_parse.y388
-rw-r--r--usr.sbin/i4b/isdnd/rc_scan.l170
-rw-r--r--usr.sbin/i4b/isdnd/support.c831
-rw-r--r--usr.sbin/i4b/isdnd/timer.c411
-rw-r--r--usr.sbin/i4b/isdnd/vararray.h120
-rw-r--r--usr.sbin/i4b/isdndebug/Makefile5
-rw-r--r--usr.sbin/i4b/isdndebug/isdndebug.8102
-rw-r--r--usr.sbin/i4b/isdndebug/main.c553
-rw-r--r--usr.sbin/i4b/isdndecode/Makefile7
-rw-r--r--usr.sbin/i4b/isdndecode/decode.h74
-rw-r--r--usr.sbin/i4b/isdndecode/facility.c906
-rw-r--r--usr.sbin/i4b/isdndecode/facility.h154
-rw-r--r--usr.sbin/i4b/isdndecode/isdndecode.8190
-rw-r--r--usr.sbin/i4b/isdndecode/layer1.c80
-rw-r--r--usr.sbin/i4b/isdndecode/layer2.c298
-rw-r--r--usr.sbin/i4b/isdndecode/layer3.c508
-rw-r--r--usr.sbin/i4b/isdndecode/layer3_subr.c1045
-rw-r--r--usr.sbin/i4b/isdndecode/main.c774
-rw-r--r--usr.sbin/i4b/isdndecode/pcause.c328
-rw-r--r--usr.sbin/i4b/isdndecode/pcause.h109
-rw-r--r--usr.sbin/i4b/isdnmonitor/Makefile8
-rw-r--r--usr.sbin/i4b/isdnmonitor/isdnmonitor.840
-rw-r--r--usr.sbin/i4b/isdnmonitor/main.c675
-rw-r--r--usr.sbin/i4b/isdnmonitor/monitor.h263
-rw-r--r--usr.sbin/i4b/isdntel/Makefile6
-rw-r--r--usr.sbin/i4b/isdntel/alias.c139
-rw-r--r--usr.sbin/i4b/isdntel/alias.h49
-rw-r--r--usr.sbin/i4b/isdntel/defs.h156
-rw-r--r--usr.sbin/i4b/isdntel/display.c252
-rw-r--r--usr.sbin/i4b/isdntel/files.c306
-rw-r--r--usr.sbin/i4b/isdntel/isdntel.894
-rw-r--r--usr.sbin/i4b/isdntel/main.c395
-rw-r--r--usr.sbin/i4b/isdntelctl/Makefile5
-rw-r--r--usr.sbin/i4b/isdntelctl/isdntelctl.878
-rw-r--r--usr.sbin/i4b/isdntelctl/main.c203
-rw-r--r--usr.sbin/i4b/isdntest/Makefile8
-rw-r--r--usr.sbin/i4b/isdntest/isdntest.8103
-rw-r--r--usr.sbin/i4b/isdntest/main.c738
-rw-r--r--usr.sbin/i4b/isdntrace/1tr6.c754
-rw-r--r--usr.sbin/i4b/isdntrace/Makefile8
-rw-r--r--usr.sbin/i4b/isdntrace/cable.txt60
-rw-r--r--usr.sbin/i4b/isdntrace/isdntrace.8205
-rw-r--r--usr.sbin/i4b/isdntrace/pcause_1tr6.c164
-rw-r--r--usr.sbin/i4b/isdntrace/pcause_1tr6.h68
-rw-r--r--usr.sbin/i4b/isdntrace/pcause_q850.c328
-rw-r--r--usr.sbin/i4b/isdntrace/pcause_q850.h109
-rw-r--r--usr.sbin/i4b/isdntrace/q921.c275
-rw-r--r--usr.sbin/i4b/isdntrace/q931.c783
-rw-r--r--usr.sbin/i4b/isdntrace/q931_util.c697
-rw-r--r--usr.sbin/i4b/isdntrace/q932_fac.c926
-rw-r--r--usr.sbin/i4b/isdntrace/q932_fac.h174
-rw-r--r--usr.sbin/i4b/isdntrace/trace.c809
-rw-r--r--usr.sbin/i4b/isdntrace/trace.h90
-rw-r--r--usr.sbin/i4b/man/Makefile5
-rw-r--r--usr.sbin/i4b/man/daic.498
-rw-r--r--usr.sbin/i4b/man/i4b.4108
-rw-r--r--usr.sbin/i4b/man/i4bctl.450
-rw-r--r--usr.sbin/i4b/man/i4bipr.498
-rw-r--r--usr.sbin/i4b/man/i4bisppp.4107
-rw-r--r--usr.sbin/i4b/man/i4bq921.449
-rw-r--r--usr.sbin/i4b/man/i4bq931.449
-rw-r--r--usr.sbin/i4b/man/i4brbch.450
-rw-r--r--usr.sbin/i4b/man/i4btel.452
-rw-r--r--usr.sbin/i4b/man/i4btrc.452
-rw-r--r--usr.sbin/i4b/man/isic.4380
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+
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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+
+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
+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*
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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
+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-;
+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
+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+
+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
+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
+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
+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+
+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
+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 *)&af;
+
+#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 *)&af;
+
+#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
OpenPOWER on IntegriCloud