summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
committerphk <phk@FreeBSD.org>1998-12-27 21:47:14 +0000
commitc7ecc129d72ba32b5d83c9a6019e93fd181d719c (patch)
tree8d5099bc7ef24151b4f6deb00d1d34a7e7ac694a
parent3f431df8ec46b86090ad59ee153872c45d4d429d (diff)
downloadFreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.zip
FreeBSD-src-c7ecc129d72ba32b5d83c9a6019e93fd181d719c.tar.gz
Initial entry of ISDN4BSD into the FreeBSD tree.
ISDN4BSD is the work of our brand-new comitter: Hellmuth Michaelis, who has done a tremendous amount of work to bring us this far. There are still some outstanding issues and files to bring into the tree, and for now it will be needed to pick up all the extra docs from the isdn4bsd release. It is probably also a very good idea to subscribe to the isdn@freebsd.org mailing list before you try this out. These files correspond to release "beta Version 0.70.00 / December 1998" from Hellmuth.
-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+
+MNYM;8R-C8X-C@X-;VWL[^_M+BZNJBLK*2KKZFGI*"NJJ*XM+N\L+:ZJ*2AHB
+MXN(BHEK:FAIZ^CK*"NJJZ\L[>UMC`X.C&R.CH^.C.SM+NTO+2VLKJ^J*.AH:
+M&AH:.LIJJVL+2_O[.[N[BZL*^EHB8F*"`@+BHAHZRFHJJRL+N_M[HR.CXR.C
+M8^.C&WM[FWO[.\OKZXMKBDIZVEKB(B+:"BHKB\N[.]L;F_N[:RI*>AK:6B+B
+M(EI:&AJ:>CI*"BKK"TN[>YL;V^/;6UN;>_O[.YN;&YO[.[L+ZZJ*RCKZFIIZ
+MFGHZ.DJJZXL[F]L;^_N["RJZ&B+B(B(B(AIZ^CI*2DH*:FJJ:XN+2SM[FQO;
+M6Z-;FYM[>QO[NSO[.\M+"XLKZ@H*RIK:VMK:FCH**JOKRWO;VWO;&XLJ"AJB
+M(H)"LH):&OHZ^FKJJ^MK"\L[>YNCHZ,CVWL[^[O+R\L+"PL+"VOKZRNK*RLJ
+M*HH*RDIZ&GKZNDJ*ZVOK2QM;(R.;^[N+:OK:(@)"P@*B&AKZ.LHJJZHKZ\L[
+M._M[FYN;>_N[^_N[NWO[.TO+RPOK*^NJZHI*"LK*"LHZNDJ*BDH*JFLK2QO;
+MHR,;^TOK"IHB@H+"0@*BVIHZBBIJJJOK:TN[^_O[F]N;._L+2TL[NWO[2[L[
+M.[L+:VLKJNIJZHI*FIKZ.OIZ^BJJ:HO[>QM;F_L[:[J:HF+BXN(B&AJ:NOI*
+MZJJJZ[L[FQL[F^-;^]M[NXOKJRM+R\M+.YM[NXN+:^NJ*HH*"KKZ&AJ:2DKJ
+MZZMK.WO;(UO[^[NKROJB8F("`B(:6AIZ>OKZ2@JJBPL;FR-C@^/;>[M[RPMK
+M"SL[NTN[2POK"PN+JZIJBFK*&IIZ.KJZ"HOKJCN;VR.C.SO[JCJ:8L+",C)"
+M6IK:&MI*BBJK"SO[^YNC`V-;&SL["XLK*@O+"RM+R[O[BZL+ZZNKJNJ*:DK*
+M2KKZ"BJK"RO+HUMC8QN[.XOZ(N*R\E*N$H(B@IIZ"BL+JJL[R\N;FV.;(_L;
+MXYM[J[MKRPM+>TL[>SL+NZLJ"ZJZ^CJZ^B(Z.KK*:[O+2]N#PT,C6UL[JOJ"
+MDN[NC@ZNDO)"&KHJ"PM+HP,;H]LCFYO;BYM+Z\M[^UNC>UL;FTN#^Z.CJVL*
+M"MIZ0J):8L):JHNJ:GOCTW-#@R-;REJRTFY.?CZN$JY"NNK+:WL;LR/;L^,S
+M0]M+(YL[*LM[.TL[(Z-;8UO;NTOJJ@HJFIJ"6F+2$AHS`PH+[^_/SX.SCR,"
+M+@X>7F;&9K[^OI**ZUN;,\_/4_//C^\S8Z.SF_K*JKO*JZI+0PO[2P,;F]M+
+M(ZL*(OIB+DYJO^JR#X_3I^]*CS]BGHY>A@;VUL:>AA[Z6U.?IV<WQU^G)\\#
+M2R(BVFX^0D*N6B+JTW/K\R_3<X.+*\OBDEJRCMHWYY)GMV\71UKOAW+&!M;H
+MZ(BXZ$9VMBZ+KZ=G-VF)5ZGI%\??@VKZ7O9&1G8VQN:2JRN/AP?G9V>GIU-K
+MRC(>1J;G]Y8[R4^WJ<M[Z0MH!L:(N,B8"(8H*,(/,Z<W5\FYJ5=)J5_/>V)N
+MAN@V!JA6!OZR>ZIOUW?']]<'IX^Z"@*&%H<)*+(9$Z>)<EY7:ACH=OC82'@X
+M#H86+Q<'=[G).9FI]^F'[HY.EO:HR%8F=D;K<P\'!T>IJ:<GQ^^KLGZB:<GV
+M4Z'G/V<29N^V`)@((&#8N&@B#LXI.8D)V=D9N4=G1^OV5O;HZ&AHIL*>#O]'
+MYP>'M]<G&R,/:EXF!N:Z>>%F"9'W"<G^IJ/(T``@</"`6#B:#Z/9`>'AP8$9
+M&8?Z^_:86+B8>"@H$B?_'RFYJ=<7YU^;;E[.7A:V1N;7L3EN\3%7V9^H9F9`
+M[$!`T##@..:I5^E!<<%A`2&)1UYHZ/B`8+B(5HZ;=[E)Z0DY5T]KKKZ&J"C&
+MYN:F?J+Y+6'.D1&7^4(@2"B0S-#`$,!XUA]A81GQK;&AF:DC3GC`()A@(%9R
+M_REIR2$AJ:<'P^:H:`C6YC:F@_\_:1&MZ?F1:0>G8+"@P.R,,`!@=@Y/X7%!
+M@3'Q65=3UHBX`+`@""@&#^G9X5EYF0DOYI;H2#@8.$:NN\]?(<V-QV&MUQ?N
+MK!"`D`Q,<*"8RI^7,>T188%!.:JV&.!8`#`@]NL/=QEA@>%)*5>+*'@8N$A(
+MR';O-W_W<;U19T'!;T>X;-#`D&P,,"@.1XDY\>U18;FYU[98@$"`H"#XCBD9
+M>=F!8=GI+XY&B!C@V%:&9K+?-\FM/;'S03%?M@"LT!`0+`SPPC<W"6'1K1&!
+M"5^OAN#PL&"@&.@;:5GAX2&A6>G+MBB(>*"8Z$;.8_^'`3T-%T=!86?@[*QP
+M4!`L[&"W(1EI(2UM\3GO;H[68)"0X';F]FLY`0'9.?D)!X+H.,AHB`CH/L^G
+M?[GM3<$O%QEY9JQLD'!P<-"PZ"G!P7G9$>TQYXAH9FB`D/"88D]/YXF!L>'I
+MI]]_[DB@&.BV-C:N#U=!S8U9OW>A6<B,#)#`\"RLX+[I@;%AX3%1D6D(V.BH
+MH)"06%+?AS<)(8'A&1>K#OX&B-AX%GX.\ONI,8WMX5_CB7DVK`SLL&#PT`#V
+MJ6%!P0$!04&9LCA8^#C@0&`H[RF)21FA67EI/WZHZ%8HR$BHCJ.G6:UM\0FS
+M1]DW(.R,4(#`D/!8VDGA`;&Q`6&A:>N(H""@H*`8J!M7R7G9&7D)U]_R%HB(
+MJ*CHJ";#27'M$=E/<PG)9C!L[##@@$"`:"?9@<&QP6$9:0>B:"!@X)C(Z`:[
+M5WG9&3D)U^?##O9HR&C61B8RJ;'MK6'?VA?)*V#LC!"`8`"`R-.YX<$Q,0%Y
+M]U\S9I@`P*#H!KXZ)\E9H9D)=S]*GL:H"$B(]G[+"?$M42$_BRE)*H!LC-"`
+MX```N(\9@4$Q,0'Y1U-*1IC`0"#H'H*;A\FAH1G)-R\RYO:H"+A(*/ZW@:TM
+M,<F3IXGWZ!`,;'#@(&`@%M=AL3$Q06')7ZO^Z""P0%AVPLOO%WGA(7DI)YN.
+M1JB(N/A(UFJYD>VM@?>/*0FCX.S,+$`@X("8.GD!,?'Q0:'7HXXV.(`P`/B&
+MZX^'B5GAH;F7#\(&J(@(2$AHQCNY<>TMP3=JA^EC(.Q,[$"@H.`X&]E!\?$Q
+M0:$WP@:H^(`PP/A>4Z?WR:'AH;F7KX[VZ(@(R`CH1JM)<6WM07?B?U>;(.Q,
+M;+!8&*`X.UFQ<7$Q02$76D;HF(`P0)CF+^?WR:'A(3EW<P[VZ`C(R(BHIHMG
+M>9%M[<&')IH?SF!L3.Q`&'AX5D=A,?$QL<$9WV;HR-@`L`#(`B?W*3DAX5D)
+MAPJ&Z,@(B(AH%H[/]SDQ[>TQ]S;FDZX@[$QL0/A(N'8W83$Q04$!&=^V"+C8
+M@$"`B#H'%^DY(>$9::>B!NC("(AH*+82?_>7R4$M[4&_"*@*ON#LS"Q@"&@H
+M+FEAP0'!P6&),FC(R!A@`*#&#_>I"9FA64EWT_[6B`CH**AV?H/'%S<W&1'M
+M<2DH..:BR'!L[$`X*/;"]YGA80'!X>FBUBAH^.#@F$:#A]<)^1F9R1<3IJCH
+M**@H*+;R;V='1X=G";&M<6FH>(8#%D`L+$`XZ';:1PF9H8'!66>^Q@:6^"!8
+M:-Y;)U?)N3FYB4>*QA;V=BAH%HZSSX\?AX?/6ZFQ40%/"&AC/VBP4)"`^"A.
+M+Q]'N6%!X1=J8D)FB-@8R%8^3Y<IZ8DY^:DC_B:&EFCHMOXRBP_GYX\S\WM/
+MV9'QR?XH8B<&8/!P0.`XYH__'XEAL6$I"^+RYJ@X&'B(_J>7=ZG)>3D7DV)>
+M%NCHJ+;F$B]GA^=?'S];#JYI,3%)RF;";^;8`##P@`@NPRION6&!6>E/(J;&
+M1NAX^%9*Y\?WZ0D):9?O3I96EE8H=K[CG^='ET=_H^).QJCRH7%AJ2\;7Z.H
+M&,`0\*#6SKY:*:'A(1E7@S[>SC:X^.C^4^>WUQ=7::G_;C86UE8V?JXZOW<I
+ME^>_@ZZ&-O96J#^QK0')9R_OO@B@D"P0H':NFB<YH6$!(5?R=C:&%FAHZ,:#
+M%VDI]Q>I1W-.%NCHMCX.+MOG5^FI1X_RIF;&=A96MK?QK4%Y9XHZ9DA@4.R0
+MH$9+OZEY(8'!68>F**B6J&@(Z/YGB<GI=[>'OVLFZ`CH!BYJ[V?WJ2E7AUL^
+M-BCHUK;&!AXI$>WQH4>^9JAX`*SLD"`&WRDYV:$!0=D?-DBX"*C6Z*AR][DY
+M:?<?KY-*AN@(*(;BS\<W%RDI]Y^J'M9HZ*AV9JY:JNF1[?&9WT;H2)A@T"SP
+MF`[W21G9&2'A22^6^-BX]HY^?J/W";F)MWO.3OX&%M9&SB-'*2E7E[<G\W*&
+MJ`@(*/;>.E.??W^Y$:T!B>)(^/B8X)#0``A+Z3EYN4F9F:F+5G@8"-X;VS-?
+M]VD)*1\.1@8&AN8F?F)/5VDIER=SZR*^MF@(:)9^*F]?9V<_[PGQD2&7_D@X
+MN+B@,/!@2`+7N7E)B3FYJ?\>B/@(YJ,O4Z_O)_=WIQJF)AZNZJMZNO.'EW=G
+MPW+.#BZ^AO;V!@YKCU\G)Z>/BCHI`8')WX:X2`B(F("`V"A[Z3GY">EIJ;</
+MWH@X:/X+8W-[2S_WJ4<S6HZ^PNJ:$N[Z+Z>'I]MBPOKJPAX&1N9"<U_GWR^[
+MPMZ""8&AZ;^VB"@65GA@('C6$RG)"2FI*1?'KR9HR-82H^\O:\N?]]>'\[*F
+MIE(:`J[N>C/?QR<#RAHJ6[OB'L;FCLHC8_OKNJ(N7AK)`6%YUXXHZ"CHF.#@
+MH,B"E[GYR8GI=\=OGB@(*.;"0X\C@W_'%_<?"N9&)DYRVJ+ZHQ\W]V?/>SHB
+MTOX&=C;F;BO3ST_O8^HNRHF!(4E'Y@@(Z*C(6*#8"&(7.9E)Z7<G7^^N=HAH
+M1@)/9[\#8V_GAW_K)C:&;COOTZ,[\Z>'9S\JCOX^;BY.WJ:^"H_GA__+SL9F
+M#[FAF:F;1JCVAC:(F%AXUJ.I24EI=X<GIU,N=N@HADI/7X_CH^^GA]^[/@;F
+M+@M#HZOZ*R^GYW\C@NZ.[M+NOGYN"I._SR.2?@LI&:'Y1XXH".BH*`CXF,CF
+MWPEY.>F';S-C:C[V**BFPT=7%^=OP[,S:^X&%I8F&N]?'\\O;W_?3_ONYL;F
+MCKI[F[LC[W^GOWON)HZ3QZFI!T,NGAZFAA:(2`C6CH\WJ1>W9Z=?OX,BWH8F
+MCDJ#,T-C8_,OK[.K,FX.KMHJ:VN+V_/O#Z];ZN("0I*NKO(ZZNHJXNXK5]FA
+MF6G[ULA("`A(N'@X%@NIF:&9:2?#*@*.)I8H*&:C1^EIU^>/0_NZ;F86*):F
+M^L_G9Z?_O[\/KZL.AK8&GD)+L_/3;T^_[UMC/P=W=V=#;@9V%A865JA6-OZ[
+M)Q>IUT<?$SL*XJ[._H[B"Z]_'W_/,POZ0E)N#DY.[B(KPX\_/\_O\WOJHBX^
+M?KZN(NJ[2[J"S[FA6=FI[J@X>+BXR,AX2!8R=_FAH;GW[T(.3AYFEBC6ABJW
+M";E)J><;,@Y>!G8H*!:F*Q]'=[?G?V]#"P(^AD8&7C+;#Y\?/V_STU_WJ:FW
+M[R[&UJBHUA96J):&0@\W*>G79R_KHD)RK@[^3L*[#^<'YS_#:L+2$E)NSO[^
+M[LIS?R<G/S-+BGI:LFX^'IX.<MJOZ=G9V3EGLG;(N'AXN/@XB/;Z1PD9&;DI
+MI\OR/GZFAL:VAJXS1^D):7</>GZ&!L9&1K:&?EKOAW?7-R?OJK(N3K[^GCYN
+M8DM3WT=W5U<WI\,2)O:HJ*A6=L9>$DN_AS=WMV<_@RIB[FZ.#FY2`HI;KT^_
+M#Q/[2F*RL@(BVIK*BZ-S[X_OL[M*PJ[.'@[SMRG)R==_8L:H:&CHZ&CHJ+9N
+M+Y>)2<DIAU-*0E(N[DX>IM[N*@\'=Q=WYQ,ZSJ;FYN;FYJ9^$HOOIV=GI\^S
+M2PIZ^CJZ^IK:VCKJ.Y,/OT_O@ZIBKHY.3KZ^SHZNXFH;DV^/;U.#NZMJ^AJB
+MPG)2TD*::R-SKR_O+Y.3\X/;2ZI*&B*"8B):2ONO_Z<GWV\[0OYF1D;&9J8^
+M+F*J8V^?)V?GGR\;N@*24G)"8AJZJCOC\Z_O+W-;ZSIB,I)R\C*"6OJ*"]M#
+M$Y/S,^,;.\LKBLJJ2^.3+Z\#2SKR#OX>'GZ^CBZ2XDI+LP__'Q\_;S.;*[H:
+MXL(R<C*"V@KK>V.S<W-#H[NJNJ*"PD("XIJ*B]O#<U-3$T.C>RLZNHHJ2QM;
+MF^OZ,NZ.#H[NTK)BHIK*ZQLS+X\/CU,#^ZJZVJ*B6OK*ZFN[&ULC8R,;NZO*
+MVF*"@N*:2HHK2_N;6Z.CHUN;RRN*&N*BNNO+(].3@SO*PJ[N;B[R(OH*JNN+
+M.]OCPP,CFPMJ.AK:>DIJ*PL[^WO[^[L+B^NKJRLK*RMKRSL[>_L[BRI*^@IK
+MF]M;H[N*&A(.#@Z.4B)*ZCN;NYM;HUO;&WN[BZOJ:NJJZPN;HR.CFTN+:^NK
+MJRLKZHI*&EIZ^CJ*JZJ*Z@HZN@H*:NL+RSO[2TN[2TN[2PL+B^NJJBHJ*JNK
+MJROKZRNJRLIJRDH*R@H*RDI*R@H*:NJJJRN+R[O[F]O;&YM[N\MKZRNJJNIJ
+M*BHJZNIJ"LK*"@H*:JKK:VOKZRLJBLHZ^CJZ2DJ**JOK"TL[FQNC6UMC6[O+
+MJXK*RDI*RFHK:PO+NTO+:RK*NII:6EK:FOHZN@IJZBN+"TM+N[O+R\M+2\O+
+M2TM+"XOKZVMKZ^OKZRNKJNIJ"@J*:FIJ:FJ*BHIJ:LIJZROKBVOK*ZNJJRNK
+MJBJKZXO+2[N[NTL+B^NKJZHJJJJJ*NJJZTL+*BMJ&GIZXEIJBNK+2RN[.VN+
+M.\L+N\LK*RN*:NKJZNLKZVN+B\M+.\OKJVJ*"KJZ2LJ*ZBJJ*RLKJZHJJJNK
+M*^OKZVMKZRNKJZLJB@H*BFHJJJMK"\M+2[M+2\N+:^LK*ZNKJBHJ*FIJ:NKJ
+M:FH*:NKJZNKJ*BK*BBHJ*JHKZXO+NSL[.TM+RPL+"XMK*ZNJJRIJ:HH*"HIJ
+MBHJ*:FIJZBJJJBJJ*JKKZ^OKZXN+:^OK:^LK*ZNK*ZNKJJLKJZNJJNHJZNIJ
+MZFLKJXOKZRNK*BJJ*JJKJJJKJRLKJZNJJJHJJZLKZRLKZRLK*^OKZ^LK*ZHJ
+MZFIJ:NHJ*JJK*ZNK*ZNKJZLK*RLK*RLK*RNJ*BJJ*^OKJRNK:BJKJJLK*RLK
+M*^OKZVMK:^OK*ZJJZNIJ:BHJ*JJKJZLK*^MK:VOKZZNJ*NIJ*JJKJ^OKZ^LK
+MJZHJ*NHJ*JJJJROKZ^LK*RNJJBHJZBHJ*BL+*ZHKJZNKJZNK*RLKZ^OK*RNJ
+MJBHJ*JNKJZLKJROK:VLKJJHJZNHJJJLKZ^OK*ZLKJRHJ*BHJ*BJJ*NKJZJHJ
+MJJMK:VMKZ^LK*ZLJ*BJJ*HJJ:ROK:VMKZ^MK:RNJ*NKJZBJK*^OKZRNJZNIJ
+M:FIJZNJJ*VMK:VMK:^LKJRHJJJNJJJHJ*BJJJJJJJZNKZ^NKJBJKJZNK*^OK
+MZVOK*ZOKR^LKZZHJZFH*RLIJ:BHJJJJK*^LKZRN+"\L+:^OKZ^LKZ^LK*ZNJ
+MJBIJ"@H*BHIJZJHKZVN+"XMKZZNJ*JJJ*VMKBVOK:ROKZZKJ:HH*BLHZRNKJ
+M*VN+BVOKBXN+B^OKZZNKJBHJZNHJ*JJJJRLK*ZLK*ZJJJJJJJZNK*RLK*^LK
+MJZJJ*JJK*RLK*ZJJJJHK*ZNK*ZLKJJHJZNHJ*BHJ*\OK:PMK*RNKJBHJJJHJ
+M*BJJJJJJJJJJJJJK*ROK*RNKJJJJ*RLK*RLKZ^OK*RNKJBHJ:NKJJJLK*ZNK
+M*ROK*ZNK*RNK*^OKJROKZRNKJZLJ"BHJZBJJ*JJJJZJJJZLK*ROK*RLK*ZNJ
+MJRNK*RNKJZLKJBHJ*BKJJJJKJZJK*ROK*ZLKJZLK*ROKZ^OKJRHJZFKJ*BHJ
+MJJJK*ROK:^OK*XM+*ZNKJJJJJJNKJZNKJRJJJJNKJJNJJJLKZ^OK*ZNJ*NKJ
+MZFHJJZJJJJNKJRLKJRNK*ZNKJROKZ^OKZRLKJZJJ*JJJ*^OK*RNK*ZJJJJLK
+M*FHKZROK:^OK*ZHJZNKJ*BHJ*JJKJZLKJZJJ*NKJ:BKJ*JJK:XL+RPO+B^NK
+M*NHJ*BHJJJNJJJHJJJNKJZNKJZJJ*BJJ*BJJJZNJ*^MKBVO+.XMKZZKJ:HJ*
+MBFIJZBHJJJNK*RLKZ^MK:^OK*RNJJJJK*RLKZROKZRNJ*NIJBHJ*ZBJJJJJJ
+MJJJJJRLKZVOKZROKZVMK*RNKJRHJ*JJK*^J*JZLJJRLK:XL+"PMK*ZLJZNIJ
+M:FIJZBJK*^OK*ZLJ*NKJ:NHJJBMK:XN+BXN+B^OKZZNJ*NHJ*NIJZBHJJBNJ
+M*JJJJJJJJJJKJZNKJZNK:PLK:XMKBXMKZRNKJBKJ:FKJ*NKJ*JJJJJNK*RNK
+MJZNK*ZNJJZLKZROKBPL+:^LKJZKJ:HJ*:FKJZNJJJRLK*ZNKJJJJJROK:VOK
+MZ^OKZRMJRNIJBBHJ*JHK*RNKJJNKJZNK*RLKJZNK*RLK*ROKZVMKZRNJ*NJ*
+M"@IJ*JHKB\L+:^LKJJHJZJHKZ^OKZ^OKJ^J*"@IJ:BJJJJNKJRNJZBOK*JJJ
+MZJJK*VN+RPN+:^LKJZLJZNHJ*NJJJRLKJRLKJRNKJZJKJRLK*^LK*ZNJJBHJ
+M*NHJJJLK:XN+:PN+B^LKJNIJ:FIJ:FKJ:NHJJJOKJJJ+ZVL+"PL+"VMK*ZHJ
+MZHH*RLK*BFHJJBLK*ZNKJZNK*^MKZVN+"PL+B^NKJBJJJNHJ*NHJZNKJZBHJ
+MJJJK*ZLK*RNK*RNK*^OK:VMK*RMK:RJJ*HK*R@J*:BJJ*VN+:XN+:^OKJZLK
+M*RLK*ZNKJNKJZBHJJJNJJZJJJJNKJBJJJZNKJJMKBVLKJZOK:VLKJZNKJRHJ
+MJ^OK*ZJJ*JJK*LH*JFJ**JLK*ZJKJJOK*^OKBXN+ZRLK*RHJB@J*ZBJKJZNJ
+M*NIJZJKK:VMK"PN+Z^OK*RLK*RLK*RNJJZNKJJKJ*JJJ*NIJZBHJZNHJJJHK
+M2_O+2POK*RIJ:HIJZJHKJZHJ*JNKJZJJJROKZROK:VOK*ZJJJJLKZRNKJJHJ
+M*NKJJJJJJJJJJJJK*VL+RPMK*RLKJZJKZ^LK*ZNJJRLKJZJ*:JKJZJLKZVOK
+MJZJJJJLK*ZNJ*FKJ*JJKJZNKJ^LKZ^LK*RLKJZJJ*NHJ*BHJ*JJJ*^MK:^NK
+M*RLK*RNKJZJJJJLKZVOK*ZLJ*BKJ*JKJZNOK*BNKJRLK*RLKJZLKZ^OK*ZNJ
+MJZLKJZNKJZNKJJJKJJHJZNHJJZNK*ZNKJZJJJROK*RHJ*BHJJJLK*ZNJ*JHK
+MZ^LK*RNKJNKJ*JNKJRNKBNKKJZMK:RNJJJJJJROK:VOK*ZNKJRLKJZLJ*NIJ
+M:FKJ*JJKJROK*RNK*ZJJ*VMK:^OK*RLKBZL*BHI*J@NJZJO+NVKB>OO+JRN[
+MVPJ*>P.+6J)**\K*B]O[FOH[N[MJ^LK*6OKJJLN[XP.[JXL[6TMJ:JOJ&B*:
+MRLIJ:JJJ*NKJBDKJ"]MCHYO[BZHJBNKJZNJ+ZRKJ"BJKN\OJZLK*"MJ*:ZLJ
+MB_L+Z^KJ*NJJ"TMKZNHK*ZN+R[L[*^KJZHJZRBJKJ@K**JJK*BJKBSMKB^LK
+M:RNKJVOKJFK*:NHKB^NK:NKKZZHJ:HHJJJJKZROKRPL[FTN+*^LKJXJZ^CK*
+MZJJ**^OK*RIK:RLJJJLJJZIJJZOK2PMKR[M+:XMKJVJZ"HH*.LK*"JOK"TN+
+MBXLK*ZHKJVJJJBJJ*JJJ*JKKR^N*BBJKZXNKJBLKJFIJZJLKJRLKZ^NKJZLJ
+MJZNJJBMK*RLK*VOK:^MKBXOKJJJJZNJJJBHJ*JJJ*BHJJBHJ*NJJ*PO+"PM+
+MR^LKJJHJZNIJJVLK:NHJZBHJ*JHJZBHK*ZOKZRLK*RNK:NJK:RNJ*RNK*NHJ
+MZFH*8NZ26DKK.]OC8P,#@V,C6QM[.TN+ZZNJZFJ*"LK*2DI*2DK*RLK*"HJ*
+M:NHJ*JJKJRLK*^OKZ^OK:^OKZ^OKZ^LK*RLK*ZNKJZNKJZNKJZNJJJJJJJNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNK________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+:____________________________________
+`
+end
diff --git a/share/isdn/1.g711a.uu b/share/isdn/1.g711a.uu
new file mode 100644
index 0000000..2ce0200
--- /dev/null
+++ b/share/isdn/1.g711a.uu
@@ -0,0 +1,322 @@
+begin 644 1.g711a
+MJNKJ*JJKJJLJZBHJJBHJJJJK*ROK:XMKZVMK:RNJ*BKJZFKJZJHK*RNK*ZOK
+MZZNKJZNKJZMJJFNK*XN+ZRLK*NKJZBJJJZNKZ^OKZZLJ:FKJ*JJKZ^NKJJJJ
+MJJJJJJLKZRNK*JHK*ZLK*ROK*RLKZXMKZRNKJBLKJRNKJZJJJJHKZRNKJJNJ
+MZNMKJZNJ*NKJZFKJ*JLKZ^LK*ZKJZNKJ*JJKJJJKJ^MKBXMK:VMKZZNJJBIJ
+M:FIJZBJJ*^OK:VNKJZJJJJNKJJJJJJNJJRLKZVMKZ^LK*JHKZBJKJJNKJZLK
+M*RNKJJNKJBIJZNHJJ^MK:^NKJJNK*ZNJ*^MKB^NK*FJ*BFHJJ^MKBXN+:^OK
+MJRHJZBHJJBLK*^OK*ZLKJZNJ:NHJJZNK:LIJ*JHK:XN+:VLKJRNKJJNJJZNJ
+MJRNK*RNJZHIJZBJJJJNJ*^OKBPN+BVOK*ZLK:^OKJZIJBHH*:NJJJBJJJZJJ
+MJJJJJBLK*^MK:^MKZRN+BZNKJRHJJJNJJJJJJRLK*RNKJJOK:^LKJBIJBHJ*
+MBNHJJJOKB[L[N\N+ZZHJ*NKJZFIJZBJJ*^LK*ZLJ*NKJ*JNJJJJJ*VMK:RNK
+M*JJJJNIJ*RLKZVN+B^NKJJJK*^LKJZHJ:HIJZBJJ*RLK*VOK:XMKZRNJJNIJ
+M:NHJJJJJZBHJJJNK*ZNJJZNKJZNJJJOK:VMK:RNKJBKJZBHJZHJ*JBNJZXN+
+MRTO+"XMK*ZNJ*JJK*NKJ:NKJJNLK*ZNJJJNKJRKJZNJJZPO+2TN+*ZJJ*FJ*
+MRDK*BNJJZ^MK:VNKJJJJJJJKJJJJJJOK:VMK:ROJ:JJJJJHJ*JJJ*ZLK:XN+
+MZVN+"PMKJNKJ*JJKJZIJBFHJJBOKJRJ*BHKJJ^OK*RLKJJJKJJLJJBNKJFNK
+MBVLK:RMK*RJJ*JMK:VLKJBIJ:JLKJBNK*BHJ*JOKZVN+B^OJ:NIJZBIJZFHJ
+MJZMKBXN+:^LJZNIJJBHJ*BJKZRMK:XN+BXMKZRNKJRLK*RNKJZNK*FIJBFIJ
+MZBHJJJJJJRLKZBKK*^N+ZZLK*RNKJZLJ:NHJJROKZ^LKJZLK*RMKZZHJZFIJ
+MJJJJJZJJ*RMKBXN+:RLKJRKJ*JHKZ^NKJBIJ:FJ*:FHJJZLK*^MK"PL+BXL+
+MBRLKJRHJ:@J*ZNHJJBHJJJOKZ^NK*BHJJBMK:^OKZRNKJZLKJZHJ*JNKJZHJ
+M*BJJJJKJ:NHJ*JOKBPO+RPMKZRNJ*NHJ*BJJJZNJZNJJJ@H*:@H*:BHK:XN+
+M:^MKBXL+RPL+B^OK*ZHJ*NIJZJHJJZNJ*HJ*B@J*:NHJJBMK"\L+"XOKZZHJ
+MJJJKJZNKJJNKJBLK*ZNKJFH*"BNJ^@KK*VO+"PN[NXLK*RMKB^LJZFKJZBKJ
+M:BHJ*BJJ*JI+*XJ+*NHK*BJJ*RNJ:VOKBVNKJZNJJNIJ:NHJJRLK*ROKZZNK
+MJZJJJJJJJBOKZVOKZ^LJJJLJ*BHJJJHJ*BJK*^OKZVOKZRNKJZHJ*BKJJZJK
+MJZNKJJJJJJNJ*BJKZRNK*FIJ:NJJ*VN+:^NKJJNKZRNJ*BHJJRLKZRLKJZLK
+M*^LK*XNKZNKJZNHJJJHKJRMK:VOKJZNJJJJK*ROK:^OKZRLKJJKJZHH*"HJ*
+M:NHJ*JJK*VL+"TN[2PN+ZROJ:FIJZJHK*ZNJ*BHJ*BHJJJJJJJNK*JMK*XMK
+MBPL+:RNJ*FIJ:NJJJJJJJJLK*RLK*ZNJJJNJJNHJ*JJK*^MK:VOK*^NK*BHJ
+MJBIJ:BJK*^OKZ^OKZRLJZFIJ:NHJJBOKBVMKZVM+"^OKJBHJZBHJ*BHJ*JNK
+MJZHJZNKJZNHJ*JLK:PO+"TO[2ZHJ:VLK:ZO*2FIJ:FH*N@HJJZNK*ROK"PN+
+M:^LKZVMKZZNJ*JJK*ZNKJNIJROH*BHJK:XO+BVMKZ^LKJRLKJJHJ*JHKZRNK
+MJZJJJBHJZJOKZ^LKJZJJJZNKJZLK:XN+:^LKJRHJ*BHJZNKJ:NHJ*BJKJZHJ
+M*BKJZNJJJJHKRXN+RPL+"PN+ZZNJ*NIJ:FKJJNOK*ZLK*ZNK*BKJZBJJ*ROK
+MZXN+:VOK*RLK*ZNKJJKJ:NKJZBHJJRLKZZNJJJHJ*NIJZJNK*^MKZ^MK:RLJ
+MZVLKZRNKJZJJJJNJJJKJZBJJJJHJZFKJJJNK*ROK:^MKZ^OK*ZNKJRLKJZLJ
+M*NKJ:FIJZBHJ*BHKZVMKBXMKB^LK:^OK*ZNJJJJK*RLJJJOJZJHJ*BKJZNKJ
+M*JJKJRMK:^LK*RNK*RNKJZNK*^OKZ^LK*FIJ"LK*"HIJZJMK"PL+RTO+"XOK
+M*ZNJZFHJJZNK*RNK*ZNK*NIJ:HJ*:NIJ:NN+ZXL+"PO+2\N+ZRLJ:FKJZNHJ
+M*JJJ*NKJ:FIJ:NJJJZLK*^N+BPL+"XN+:^NK*NKJZBHJ*BKJJJLK:RNJZNKJ
+MZJJKJROK*ZLKJROK*XL+Z^OKZZLJ:FIJBNHJZNKJJBMKBVMKZROK*ZNKJJJJ
+MJZNKZ^OKZRNK*NKJZBHJ*BJJJ^OKZVMKZZLJZNJJJ^OKZ^LK*ZNK*ZLK:VMK
+M*ZHJBKK*RLIJ*BHJJROKBVN+B^OK:VMKZROK:^LK*ZNK*RNK*BKJBHJ*"LH*
+M"HKJJVL+2\L+:^NKJJHKZRLK*RLKJZNJJZNK*RNKJNIJ:FIJ:HJJBRMK"PO+
+MBVNKJBHJJZJJJBHJJBLKZVLKJJHJZFKJ*BHJJJNK*^L+R\M+RVLKJBJ*BFKJ
+M*JJKJRLKJJJK*NIJBHH*BFJJJVN+BXN+BPL+"^LK:RNKJZNK*ZNK*RLKJRIJ
+M:FKJZBHJJJJK*ZLJ*NJJ*BOKZVN+BXL+BVOKJ^J*"@K*"HJ*:JJK*RMKBVMK
+MZROK*RNK*ZNKJZNKJZLKJZHJJZMJZBHJZBJJJJMK"PN+BXMK:^OK*RHJZBHJ
+M*JHK*RNKJJHJ:LK*RHKJ*BMK"PL+"PL+B^LK*ZNKJBKJZBJJ*VN+:^NKZFIJ
+MZBJJ*BHJ*NJ*:JLKZXL+BXOK*ZJJJ^MK:RNKJJJK*RLK*ZHJZFIJ:HJ*:BJJ
+M*VL+RPN+Z^LKJJNKJZJJJZNKJBHJ:FKJ*JJJJBOKZXN+BXN+ZZNK*^OK*VMK
+M*BIJBNHJ*NJ*BFKJ*BJKZROK*ZNJJ^N+BXMKZRNJJBHJJJJKJZHK*ZNKJZNJ
+MJZNJJJJKJZNJ*JJKJJLKJRNKJZJJJ^OK:VMKZ^LKZRNK:HKJ"@IJZNJ*ZBJJ
+M*^N+BVOK*ZJJJBMKB\L+:RLK*^LK*ZKJ:HJ*BFKJ*JHJZJJK:\O+RPN+Z^OK
+M:RLJZNKJZNKJZJJK*^LK*ZHJZFHJZNHK*ZMKBXN+BVLKJZJKJJLKJZHJ*NKJ
+MZNKJJJJKJZLKJJNK*ROKZXMKBVOKZRLK*ZKJ:NHJJPN[.TOK"IKB`N*:ZLL;
+M(Z/[BZIJBNKK2WM[.ZMJBKK*:JMK"\L+*VI*NDI*"FJJJRNKZNHJJNN+R\L+
+M:^LK*ROK:VN+B^LK*NIJ:FIJZJHKJZKJ:FKJ*JOKBVLKJZNJ*BJJJ^OKZ^MK
+MB^LK:ZN*:HJ*:JHKZXO+2\L+:VOK*RNJZNIJZNJJ*BHJJJJKJBKJBHJ*:FIJ
+MZBJK*ROK:^NKJRLK*RLK*^MKBXO+R\L+"PL+BXOK*RLKJZJK*ZOJ:NIJ:FH*
+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
+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
+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
+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
+MZ^OKZZLJJBKJ*BJJJJJJJBNKJ^LKJZNKJZLKJZNKJZJK*^LK*RLK*ZHJ*JJK
+MJRLK*ZNKJ^LK*RNKJBKJ:JKK*BHJ*JJJZBHJJZLKZ^LKJROKZRMK:^NKJJHJ
+M*BHJJRLK*ZNJJBHJ*NKJ:BHJJRLK:XN+:RLKJZNJ*BHJ*NHJJJNK*RNKJZJJ
+MJJJJJROKJRKKZ^MK:XN+:RNKJNJ*BHIJ:BJJ*ZLKZ^OK*ZNK*VOKJRHJJRKJ
+M*BJKJZNKJZJJJZNKJJJK*ZLK*ZNKJZNKJJNK*^NKJZHJJJOK:VN+:RMKBZLK
+MJZNKJBKJ:FKJ:HJ*ZBHJJJHJJNN+"PN+:^LK*ZLKZVN+BXNK*NJ*RLK*BHKJ
+MZBHJJJLKJRLK*ROK:VMK"XN+BVLKJZJJZBHJZBJJJPI*BNJJJ^MKZVMK:^OK
+M:VL+RXMK*ZNK*FIJ:NKJZBJJJRNKJZHJ*BIJZJJJ*JNJ*^OK:XN+ZRLKJZNK
+M*ZNKJRHJ*FIJZJJKJ^MKB^LKJRIJJRLJJZNKZ^LKJZNKJJLJ*BKJ*NHJ*BHJ
+MJJJJJBOK:XL+"\L+BVMKZ^OKZRLKJZJJJZNJZNKJ:NIJZNIJ:HIJ:JJKJBOK
+MZ^OK:^N+BXMKZROJZNNJ*BJJ*NKJJJHJJROKBXN+RTO+BVLKJZHJJRNJZBJJ
+M*FIJ:FKJZFIJ:HJ*B@J*ZBJJZVN+BVOKZ^LK*RLKZXN+B\O+"\L+"PO+RPMK
+MBTN+JZNJJJNJZBKJ:FJ*2KHZ.OIZ&J):6EK:&OI*"FJJ*^MK2SL[>YO;HV.#
+M@P-#P\-#`Z,;F[L+NYL[.QN;^[MKRAJ"DN[./GZ>'AZ>_@ZN<N(*:WMC0W/3
+M+V^/#P^/;^\OKU,3\Y-S`^.CNPNCT^]S0Z^C"MKNIN8FAL8&1K8&YB;^DLI;
+MKX]/?W__'Z=?7^>G?\\OPYL+JZOJNMJ"$JZN[HXNKBZNKN[NKO(BRFO;LQ/O
+M#P\_I^<G9X>G_\\#BJ)2/MZFA@8&Q@;F'K[N(DHJB\L+N_N;HV,#PW/3KV\/
+M3S^_3P]OKS.#HSLJZ^__X^,?+^N;:CZ>/H9&AK:6M@8&)KZNRJ/S;_]__Z??
+MOW\_KW.3H_NCFPN;&RNK:VJZ^J+"PC)24E+2PJ+:2J,?!Q]G5T=?IT\J^J+>
+MYJ;&EO;V]@:FSMI+6]-ODX,#HUM#8]O#\X-CXUN#T].3<Y/S(^O*2KH*"IH*
+MSV=#4S<G\\]S<G+"9D;FMI:VMO9F/F[Z6_.//\^/;S/C,\-;(R-;8X,[>T,S
+M,[,#8]O+ZIJ"@F("8N)[YU_CQQ???]][`NKNQF:&EI;V%G9F'J[J>]-/#V]/
+M4UM#$P.S\Z.#$T.;6^-C`X,C&POJFH)"@F+B^L-'A[/'U^???[K^DCXV-I8H
+MU@9FI@Y"(]\?CR\#ZCI"'MZNHBHS+T_GQ\<'IP]SXVIRSAY>OA+:V[>9(?E'
+MA^>KGJB8H#@(""B69CL'-^??GV?G^][&AIYNSKXB#\?WMP<'!Z=;KM[F9B9^
+MC@+K0P]?Y^<I84%9I]XF]NCX("!(YHXN\DJ_E[<#?B8N&OZ6EHX/Q^>O0Y^'
+MI]-K:\/#&K[>#IJ;`^-S_Z>G?[?A<8$7QNBH:#C@8)AFJLJR[@L'=Z]FJ$9J
+M+])&'D^IJ?]",O/?CRKB.T^/"KX>TCLSVPN#[[\GR3%1@:=H.+BX>.#@2"XO
+M@YINRV?'JQ8(5KH_*MZNIVGI;UXFBA^GLSH+CP]+CJ:.2P^_\ZHK$_?AK5&9
+MIMC8>+B8(-C60Z>3\MY*7W\.:$A&SR=KCJO'*7?*-D;B'V?_PR-S\ZN._@*O
+M7T\#@],70>U1:<@`8!AHR%@8-D^W7W(&#D\?+FC(AA/?,PLO!W>GTO9&0O_'
+M9X]+BMJ"$I(JKY\??X^?>:UM04I@,("X]F@82*:G]W^>UJ8[(QXHJ*;JTS]G
+MQ\??ZEZ&?BM?-\?/2@[.LFMS#T^_GY_7L6VM"3@PL""6YLAXB'+'UW^&5N:B
+MVN:6MIY*#[?7MW\*IH:>^F_GQR?3HCZ^HN-_IT^S<P?A[6UA-C!P`&@"QKAX
+MUO-7J2L6J`:N[B8&9CZ*IU=79[M>QEZZ;R<')R^*CD[RNT_G9W^O9V'M[>&H
+M<!#`UA.2:'AH@A=I[T;HJ&8N>B+>MN:O*6G'6G86/B^'1R?S:B(24EK;OX<W
+MAX<9K6TQ"T!0<)C++R;(N/;3Z9>*]HCHMH+[4K;6$G=)B5.6R!;[EXFI#S)N
+M$B*JVZ]?!\='F='M\0^`4!"@PH_2*,A6ZBFICQ[HB*C^:]IFUD['R0D_]CAH
+M@C<)Z1^R3O*+;P\OOZ?'";'M4?G(\!#`5FM:]@@H?N>IYQI&J*@&8K+&*#9O
+MB;D7+HA(Q@_IB;<[/CZ:+U]_S_]G27%M46E8T-"`7G^:J#AHKE>)Y^[6*):^
+M"GZHB&8'.3D'QOBX)B>)Z1\27NX;)\=GIQ^WH:UM,?/`4)!8>L_.B#BH>VEI
+MGSZHZ$9:\A:X"%J)H3GS:!B(:BFYUXK&1I+_]S=?OX>948W1!X"LT"!Z9V*(
+MF&CK"3G'ONB(-LH*EGB8WFDAV9]HH+BRZ7EIFT9V#@_WE^?/IWFM#5'W@*Q0
+M(/IG0DB@R`I)>7=N:,B6>@NV^'BF*:'9?X@@.+(I^>ECAC:./U>IAR\?62V-
+M<7NP+!`X/V>FF""([_DY!QYHB&8[,N@82#LYX;FB^*!H,XFYMS)&YFO'*9>G
+MC_?!;>TAB)!0`&;GH^B@F&:7^2EKEBC&FJ(H6-B&Z>&AYRA8.*Z7"==;GEY*
+M7Q<79Y^W(2UM0<XPK+#HWT]VH*!67SD);X:H!KKJUJ`@J'<A(9>6V#@^]PE7
+M8Z;F6J?7J0<_IWE1C9&/0*SPR#^GQE@@Z,])"2^&J&:+,T:@@,AG(6'I!ACX
+MWL?I=QN>_NH?MW?'YS=9K8UQ&["L,(A_[Z@@H/;G2:DZ-O:N;[MH@("H*6$A
+M1U:8"`)'EU\K<CJOI^=G9P?765%M,=O`$,!HD^N((-CF!PF7LL8F"@^:2,"`
+M%NGAH:=6N%;*YX?/.ZJ;$^^_9Y?IR6$M[6$V,'!@MO->>.!(FI?IO_Y>.D_S
+MMB#`6)HYH6FZUE8^P[_OLT-#(^OJK_<)23G!+:TY2/"PV*;*J*"@UH\7-PH>
+MVO^'HCC``*@WF4E_'D;^^BJJ&W]G3VJN^J?IN4G9$6TQRP!P8%8J)IC@N/I'
+M1UM>DC\'KZC@P)@KB<FWZCY.$M+RR]^WYSO.#J\I.;F)82TM>4CP0#B^<L@@
+MV.;GQ_-^OK_WAZ:@P*!>-^DW$ZLJHGZ&;L_W-V-^7@N72;D)&5%M01Y`,!C&
+MKN@@6#;_)VJ>OA]7!XZ8@"`6[P=GG[_/ZB:6)D_7%S,>'HM'Z6DIR?$-K>=@
+M,-@V)FC@H+8_G_Y&SF>)!T[(H!B(IKL_1_=G:^8VIL-'MY\ZCM)#]VEI::$M
+MC6&6P&#H]NB@X(AJWR(VGO]I5UI6.'BXZ%Z[A]<W#RYF)G(O)R<OND**_Q=I
+MB4FQC:UG6&!(%H@88/B.+\IVQJ\IZ0-&J,CX."AR7Q>7IR,2?OYB+R>G8UKZ
+M8^=7*6G9K8V!-B!XMFA8X*!&@RI&5NK7:2>F!H:(V!B6+S?WIT]OBGXF8I\'
+MCU+N>U\WEU=IX>WMR<@8%F9X8&"XTFKFJ.:'Z3<K_OI>>.!X/K__OR>WIZ[&
+M?N_'WTHNF]^GI\<I28'MK;>(:"968`"@Z,ZFEK9J=W?_Z^OO9J`@B'(+:C_7
+MJ6_F!LH?/XOB^[]O6W^I"<GA+5&WJ!;>:("`&"@F1I;F8T?GK^-O[U8@6*A^
+MWO+'B:G[)G)/?XLBVT]3^BMG*>DIH:VMZ7:&@J@`P!CH]BBH?F]'W^\_Y]\V
+MH-BH-JBF1\D7NU)SIP.2JA\?:ZX[QY>WE]E1+8GF>A.H0,#X:(BX*)(/I^\?
+M-\?_YOCXB&@(9L?IAQL3AY]";J_GDY)28V>W!_>9$2UY,O]GUD#`.$B8&"BR
+MVS-SQZEGDXIV./C(:$;SQ^??9\?_ZDIOIP,24LM/?U]'"4$M@>_'*?Z``#AX
+M(*!H3D**D[?I1Z^/:HC8..BH9CLGAP<'9S]3;Y_O6JY*PY.O)Y=Y<1$))\FW
+M"``8N."`F#9>'BJGZ2D?OP?R^'@HZ`BV,Z>?)[<W)P]_IX/RHNMKNQ,GU^'1
+M`7=)><L8H`B@P&!(EM;F8W=IMW^W%Q[XZ/;(.(8/L_LG5Y<_SX=G6ZYJXZLB
+MXP<IX9$A*5E)TCBX"(#`(#AH:.;OUZDGAZDWY@CVJ/A()LMRJD<I]S\'5\=+
+MFG/[KBZOY[_)\0&IF:%_*`BH(,!@6,C(J.*'U]_G*>FCJ(:F"/C6`MZ>GQ>W
+M7S?I=V]+;UNN,JJS^Z=A,6D)@0GNUF9(`&`@F#BXQOO''X\7*9<BAL+V.`BF
+MWM9"9V?GMRG71U^_/PL2(DMK>@=A`9=Y`1<^IE(X`""@&)CXMMH/^P^I%W<?
+M.IHF*.C&!JA.OS^?1ZG7]\=?G[MR2KJ24KN7X:&7X>$G2@I.H.`8(-B@N+;N
+M*PH'=V<71_-:_O:HMA96SOM3)Y=7UZFWI]]CPOJZCJX*,TGAJ?D!*:_3&P@@
+M>*!8V*!H9L)N4_=?-RG'BDJ2UA9&ED8RKS]'=Y>IE^<_;\M"HI)NKJXK:>$I
+MR4$)O_]3J"`XH*#8(`@VSI[[MQ_'J5=#:HMF-D9&QOY+\R<'MU>7!Z?_<_IB
+MDHY.;@)[Z2'I.<%I)Z=O*%BXH%B@H,C6)H:+)P]GU^F/F^\N9D9F!B8:`U_G
+MQY>7QZ<?[YM*\M(.?GY2XM\9.5=A6;<G9UKX"#C8V""8R/;VAC/OGX<IJ4\/
+M3Z*&ADXFIH+3_W]G-W='AV<_>SH";E[FWLZNZG<9B0DAN?<?YXX(B$CXH-@X
+M"*@6WKKO3Z=7%]]OS[N^ILZNCD(SWU_G1W='YU]/$\NZXI+NSA)ZRHK#IX?G
+M_T_G7T-[*E*>3A[&MD;&=I;V1N9^4FKS[T_?_U/S;Y/[6V,CFSM+HY/S4X_/
+MCX^/@\L[J]HB@C+*CZ</_[>W'P_OJE)NIC:6EE8HJ-9VAOYRRF/OST_/[Q.O
+M+_/#D^_O+R]O3T\/[^^O,R/+:@(2DN[.#JY2\CM?YW_'UT??G^^ZPM)>!D;V
+MUJA65G:&?JX*(Z]O;^]OCR\O;P]O[^^OK^]O;X\/[Z]#N^IZ0BYN;HX.;BZN
+MHI.G/Z>7UP<GIT.B@@Z&1D:6J-;6%L8>;B*[,X\_SR^/OV^O[Z_3KU/ST^\O
+M+R\3@]O+"MK"4NYN;NY2<N+Z>HM_AQ_G%Y<GW_^;(H(.YH;&=A9V%I;&IKZ2
+MBGLS+^\O;[^_SP_/SX_O+V_O4Q,#8Z/+*KJZFL+R0K*NKG)R\F(:VBJ/YU^G
+M=Q>')Z<OJKIR7F8&EE;65JAV9GY2.KOS;V^O;S\_3P_/SX_OK],O[R]S0X.;
+M:XKZVMJ:HD(RPF("`H*B^CI*J@/_IQ^']\=?G^^K`BX>9@8V%A9V=C;FSL+*
+M>Y,O+Z]O#X\/#V\O4_.#XP/SD]/3<\-C6\OJJJK*&B("PL(R<@*:>MJ:NDOO
+M#^]?!V=_/^_+.L).'EZ&-K:V-D8F#N(J>Y./+],O+U,O+Y/S,R,;HZ-C$R^O
+M+^^O0^-["^OJ6K+RDF[.;E*20J+Z2KHZ.T]_3^<WAW]/TXO*PDY^GN9&1K8V
+MQB:^\HJ;0W-#`\.#`Q.O<S/S0P/#LU///[^_OP_3PWLKZDH"KBYN3KX.CBXR
+MPJ(Z"@HJ"S/_'_\GAU^/K^,*(I+._A[FQD8&9J9.<LJ;8X-#\[.#8P-#LP,C
+M8_.O+^]/GY\_#^^3H\L*&H(R+DY.;@X.TN+:RFN+Z\M["^KJ"V/#H[-O;W.#
+MXYL+:MK"<NX^GIY^_CYN8CK**HO[&WN;([-S<_,S<],3<U/O;V\OD\-;B\KZ
+M^CJ:XB(:XK*R,C*"8@*B>EI:.DI*JHL+XZ^O4P]/[U-38TOK2L)R$HZ^3KY.
+M#NZNPJ):RJOKR_O;H\/SDU,O[V]OCX]O+Z]3LX/C&VN*FL)2[HX.CFYN+G(R
+MPN+:BHN+"YM;^_L;FR/S<Y/O#^^3\X.;RXK:XK+NSDX^?C[.CJZR(CH*JLL;
+MXT/3+V\/ST\_/P_O[].#&TN*^OI:@L(R4E(2+FZN,C(R(OIZ^KH*JPO+>^,#
+M\Y-STR_OK^_OD\-#6RH:HO+N#DZ^3KX^SBY2\AH*ZCM;H[,3<W.OKU.OKQ,3
+MD\,C(UO[2XNJ*BKZ`H(B\NXNDM+20@*B2NKJRZ-;6X-CH^/C6QN;>[L+B\N[
+MBZOK:^I*"KH:VMI:&II:6AI:6DHJRBIKJJN[^SN;6QN;&WM+2WN;.\N[2VLK
+M*RLKJRHJJBJ*:NKJZHK*"@K*RHJ*BHJJ:ZN**NOJRJHK:NJ+RVL+N\N[F[L+
+M2SL+:VLKJBIJRIKZ"FI*.BJJRFKJ^KHJ.AKJ:^KJ"XMK2TN+^QN["SO[2TL+
+MZ\N[BXM+RXL+JXHJJPHZ"FJZ&AIZ2LHZ"NN+Z^N+2[MKJ^LKZNJKJFKJJJL+
+M>_M[FWO[RVLK:CKZNKIZ&KHZ^OKZ^@IKBXN[^[N+*FKJ:BHK:VL+RXMKR[N[
+M^WL[2PLKJJNJ*NKJB@I*>CJ*BLKJ*VN+BVL+"XM+2PO+.VN*JBMJ"DI*:BKJ
+M"NHKJJJJJJMKJFHJJFIJJJHKZVMK2TL+BXN+:ZLJ*^NJ*BOK*ZLKJHKJ*LI*
+MBBIJ:JJK*ZOKBXO+NSL[^SO+ZZKJ:FJ*JJL*:JHJZJLJZBKJRFJK*FJKJBJK
+MJNJKZZKK2TL+2POKBVOJZJIJBJHJBJJKZHHJ:NJK*^N+RPN+B^OKB^NK*ROK
+M*ZHJJBIJ*JNKZFHJZHH*2FIJ*BKJJNMKBPN[NTL+RXLKZRLJJ^LK*BHJB@H*
+M:JHJZBHK*ZOK*ZMKJXIJJRKJJXN+BXN+"VNK*XNKJBOKJBIJZBJJJBN+ZROK
+MJVJ*:JHKZNJJJBHJ*^LKZ^NJJJLJ*JJKJZOK*ZNJZVLK*ZLKJNHJ*JLKZZNK
+M*ZNKJZKJ*BKJZBJJJJLKJZNKJBJJJZHK"POK:PMK:VN+"XNK*JKJ2DIJ"FJK
+MJZNKJNHJ*ZLKZ^LKJJJJZ^LK:VNKJJKJZNIJ:NHJ*JOK:^OKJRNJJJOKZRLK
+MJROK*JHKJZHK*ZLK:VOKZVOK*ZHJJZLJJBIJ:JJ+:ZKK*VH*BFIJZJHKZVMK
+MZ^OKZ^LK*^OK*ZKJ*BHJ*NKJJJNK*VMKZROKZRLJ*JHJZBJKZJOKJZJKJ^HJ
+MJZNKJRNKJZJKJZNKJRLKZ^LK*ZKJZZNJ*ZNKJZKJZBHJZJJJJ^LKJRLKJJJK
+MJZOK:VN+:VN+*ZJJJRIJ*NKJ*NHKZZNJJRLJ*RNJJJJJJJJJJBKJ*JHJJJNK
+MJBOK*RMK*ZJJB^NJJRLK*ROK*ZJJJZNKJJJJJJJK:^LK:^LKJZNJZBKJ:@H*
+M"HKJJBN+BPN+"PN+:^MK*ZNJ*JJKJROKZ^MK:^NKJBIJBNIJ:NIJZNKJ*JLJ
+MZNLK*^OK:PN+BXMKJZNJJNKJ*JNKJZHJZBJJ*JJK*ZNKJRHJ*JLKJ^MK:^OK
+MZVOKJZJKJNHJ*BHJJBHJZFIJ:HIJJBMK"XN+BXMK*RNKJPO+*RLKJRHJZBHJ
+MJJNKJJJJ*NKJBFIJZBHJ*BJKJRMKBPL+:RNKJZNKZZLKJZJJJJNJ*^LKJRKJ
+M:FIJJJNJJRNJ*JOKZVMKBVNK*RLK*ZNJB@HJ:FHJ*BJJJJNJJZLK*ZLKJJLK
+MZXN+"\N+Z^LK*JJK*ZHJ*NKJ*NKJ*BOKZRLK*ZJJ*BHJJJJK*ZNKJRNKJJJJ
+MJJJJJRKJZNKJ*BHK*RL+:ZOK*ZNKJZHK*^OKZVMKZ^LKJRKJZNIJBFIJ:FIJ
+MZJJJJ^N+RPL+BXOKZRNKJZLK*ZNKJBJJJJLKJZNKJJJKJZJJ*BKJZJJK*^OK
+M*^N+*XJZB@IJZVOKZ^LK*ROJ*NHK"PL+*RLJZPNKBBHKJHIZ"NKK*ZN+JVKK
+M2VMK:PO+BXNJJZLKZ^NJ2DHZ2NKJ:LKJ*VO+2[M+BRNJJZH*RLHK\RM^&B-;
+M8UYV6]?C&[O.IU?::.9_";?FJ([''R8H@I^_BZOOR[Z&<LN?YW]*AKI^GB(N
+MTX?WE_?;!B9:ZPOB7OJ/6_XV!H+GQP_+"AO;0JZK\].;>WMJZ]LJ8HHZIL;Z
+M,X._3R*K/^HNNV)B$T^:OD/S&]OZ0N)Z4J*S+[.JTA("ZR_OV]J[FTHB>FNC
+MSUM":B+";L(K:L.#N[HJDY.#&OK+VCK:+G*+>QMC`VNZZRMJ^HJ:J_LZJOM+
+MJ@H+X^-[RRK*RCLJ\DJK*DHKP^-+JY*B^SMZ>DN;R^IB.H)J[W.ZHBIJ*NM[
+M8W/[.BI*^DN+ZEJB:FH"VOJJ,R/+BKK+BYM+NNO;H^J"R\LZ:KLK2JMK>XMK
+MJAI*FIIKBHKKF^N:*TN[NZO*.@O[ZRMJR[N[^\JZ:TNK^MK:(CKKN\.CJGLC
+M2YIZJXKKZRH*ZFMKB\J*:XL*NAM;JLKZ2FHJJ\O[*VNK>KJ+:OH[NRL["SKZ
+MJCL[.ZHZJZLKNXOKBZNJ*^I*ZLOK:@KZBFH**OM;RZMK*J(*2PI*NYOK:[O+
+MZOHJRAHJ2XOJN\MJ*JOZFHN[ZHKJ*XN+:^J*"QM[NXHZJBLJBNJJ2WL[JQH*
+MZNKKJHJJBSN+ZJL*:FHJRRN*ZFO+*XJKV_LK*ZNJ:FKZ>KH*:TLK*BO+*ZLK
+MBFHJ.TN+N^N+"ZJZ"LKZ:BLJZFNK:FL+B\LK:HN[*DK*ZJH+RZMK"POK:^I*
+MNFHJZJLJ*JH+ZRJK:BL+"ZHJZ^N+:TOKZ^NKJZOK:NHJZHOK:BHKN\MJVKHJ
+MZPMJJFNJ:RMJJRJJJRLK*JMKJ^LKZZJKZXIJJJNJ:JKJJRLKZPL+JXL[:^IK
+MZXI*JCMK:PNKJNHKZNJJZZJJJ\IJ*B)N4F+Z*LM[6R-C8V/CHUL;FSN["XLK
+MJRKJ:HH*"LK*2LK*RLH*"HJ*:FKJZBJJJJNKJRLKZ^OKZ^OKZ^OK*^LK*RLK
+M*RLK*RLKJRNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNK
+MJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZNKJZO_
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+M____________________________________________________________
+9____________________________________
+`
+end
diff --git a/share/isdn/Makefile b/share/isdn/Makefile
new file mode 100644
index 0000000..dbc7973
--- /dev/null
+++ b/share/isdn/Makefile
@@ -0,0 +1,20 @@
+# @(#)Makefile 8.1 (Berkeley) 6/8/93
+# $Id: Makefile,v 1.8 1998/01/03 14:13:46 wosch Exp $
+
+FILES= 0.g711a 1.g711a 2.g711a 3.g711a 4.g711a 5.g711a 6.g711a 7.g711a \
+ 8.g711a 9.g711a beep.g711a msg.g711a
+
+CLEANFILES+= ${FILES}
+
+all: ${FILES}
+
+${FILES}:
+ uudecode < ${.CURDIR}/${.TARGET}.uu
+
+depend lint tags:
+
+install:
+ ${INSTALL} ${COPY} -o ${BINOWN} -g ${BINGRP} -m ${SHAREMODE} ${FILES} \
+ ${DESTDIR}${BINDIR}/isdn
+
+.include <bsd.prog.mk>
diff --git a/share/isdn/beep.g711a.uu b/share/isdn/beep.g711a.uu
new file mode 100644
index 0000000..c1fc86d9
--- /dev/null
+++ b/share/isdn/beep.g711a.uu
@@ -0,0 +1,106 @@
+begin 644 beep.g711a
+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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